Can a Java class add a method in time?

Can a class add a method to itself at runtime (for example, from a static block), so if someone performs a reflection of this class, it will see a new method, although it was not defined at compile time?

Background:

The structure I use suggests that Action classes should be defined that have a doAction(...) method, by convention. The structure checks these classes at runtime to see what types of parameters are available in their doAction() method. For example: doAction ( String a, Integer b)

I would like each class to be able to programmatically generate its own doAction() method with various parameters right on time when it is being tested. The body of the method may be empty.

+49
java reflection code-generation javassist
Jul 13 2018-11-11T00:
source share
9 answers

It is not simple. When a class is loaded by a class loader, there is no way to change the methods of loaded classes. When a class is requested, the class loader will load it and bind it. And there is no way (with Java) to change related code or add / remove methods.

The only trick that comes to my mind is a game with class loaders. If we remove the custom classloader, the classes loaded by this classloader must be deleted or inaccessible. The idea that comes to my mind is

  • implement one custom classloader
  • load a dynamic class using this custom classloader
  • if we have an updated version of this class,
  • remove the custom classloader and
  • download the new version of this class using a new instance of the custom class loader

I leave this as food for thought, I can not prove if this leads to a solution or we have pitfalls.

As a simple answer to the question: No, we cannot change the loaded class, since we can change the contents of the reflection fields. (we cannot add or remove fields either).

+50
Jul 13 2018-11-11T00:
source share

Andres_D is right, we can do this very well using custom class loading, here is a detailed guide on how to do this: http://www.javaworld.com/javaworld/jw-06-2006/jw-0612-dynamic.html ? page = 1

This article explains how to write dynamic Java code. It discusses compiling source execution code, reloading classes, and using a proxy design pattern to make changes to a dynamic class that is transparent to its caller.

In fact, a researcher in Austria wrote a JVM that even allows you to reload classes with different type hierarchies. They accomplished this by using the existing stream persistence points to generate the full “lateral universe” of the object and all the links and link content associated with it, and then after dragging and dropping with all the necessary changes, they simply replace all the changed classes. [1] Here is a link to their project http://ssw.jku.at/dcevm/ Oracle sponsorship certainly provokes interesting thoughts about future plans.

Less intrusive changes to the bodies and fields of methods are already possible in a standard virtual Java environment using the JPDA hot-swap capabilities, as presented in Java 1.4:
docs.oracle.com/javase/1.4.2/docs/guide/jpda/enhancements.html#hotswap

I'm not sure if he was the first, but this 2001 Sun employee document seems to be one of the earliest suggestions that mention HotSpot's hot-swap capabilities. [2]

LINK

[1] T. Würthinger, C. Wimmer, and L. Stadler, “Dynamic Code Evolution for Java,” presented at the 8th International Conference on Java Programming Principles and Practices, Vienna, 2010

[2] M. Dmitriev, "Towards Flexible and Secure Technologies for Developing Java Application Runtime Applications," in the OOPSLA Workshop on Engineering-Complex Object-Oriented Systems for Evolution, 2001

+19
Sep 14 '12 at 23:26
source share

I have never tried anything like this, but you should take a look at ASM , cglib, and Javassist .

+6
Jul 13 2018-11-11T00:
source share

No, this is not possible (easy) in Java.

It sounds like you're trying to use Java as if it were a dynamic programming language. For example, Ruby has public classes: you can add and remove methods from Ruby classes at runtime. In Ruby, you can also use the method missing method in your class, which is called when you try to call a method that does not exist in the class. Such a thing also does not exist in Java.

There is a version of Ruby that runs on the JVM, JRuby, and she has to do very complex tricks to open classes in the JVM.

+4
Jul 13 2018-11-14T00:
source share

You can have a doAction method that does whatever you want the generated method to execute. Is there a reason why it should be generated or can it be dynamic?

+2
Jul 13 2018-11-14T00:
source share

I believe you need some kind of bytecode modifying a tool / framework like asm, cglib or javassist. You can achieve this through aspects / weaving as Spring did, but I believe that you still need to define a method first.

+1
Jul 13 2018-11-11T00:
source share

A proxy can help. But you need to create a proxy instance every time you want to add or remove a method.

+1
Dec 27 '13 at 15:19
source share

I am not sure if this is possible. However, you can use AspectJ, ASM, etc. And weave these methods into the appropriate classes.

Another alternative is to use composition to wrap the target class and provide a doAction method. In this case, you must delegate the target class.

0
Jul 13 2018-11-17T00:
source share

It seems like it is not possible to dynamically add a method. But you can prepare a class with a list of methods or hashes like:

 import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.HashMap; public class GenericClass { private HashMap<String, Method> methodMap = new HashMap<String, Method>(); public Object call(String methodName,Object ...args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { Method method = methodMap.get(methodName); return method.invoke(null, args); } public void add(String name,Method method){ if(Modifier.isStatic(method.getModifiers())) methodMap.put(name, method); } public static void main(String[] args) { try { GenericClass task = new GenericClass(); task.add("Name",Object.class.getMethod("Name", new Class<?>[0])); } catch (NoSuchMethodException | SecurityException e) { e.printStackTrace(); } } } 

Than, using reflections, you can set or disable the attribute.

0
May 15 '16 at 10:45 pm
source share



All Articles