13

I have the capability to extend a class at compile time, but I need to be able to create an instance of this subclass at runtime using an instance of the superclass that was already instantiated.

This should be possible in theory because superclass constructors are already called before the subclass constructor.

I do not have access to the program sufficiently to change the instantiation to my subclass nor to interrupt the original instantiation.

Use Case: There is an existing array of instances of class X. My code is loaded in after. I need to override one of the methods of one of the instances X with my loaded subclass Y extends X. The parent program accesses the objects only through that array, so I want to replace that array element with my Y instance, but it needs to behave as if it were instantiated originally into that array. I cannot just enclose the superclass instance and forward calls, and there are difficult complications with reinstantiating the superclass.

I hope that is more clear.

JAKJ
  • 289
  • 1
  • 4
  • 14
  • 3
    Please rephrase the question. – Michael Slade Apr 06 '12 at 16:11
  • 1
    Can you also provide an example of what you're actually trying to accomplish? Instead of just your desired, but possibly impossible, method of doing so. – millimoose Apr 06 '12 at 16:16
  • Assume existing line "public static Foo foo = new Foo();" that I cannot alter. I have "public class Bar extends Foo" and I want to do "foo = new Bar(...)" such that it was as if the first line was "public static Foo foo = new Bar()". – JAKJ Apr 06 '12 at 16:24
  • For those just looking to extend a class at runtime, and not to change the runtime type of existing objects, see [Extending class at runtime](http://stackoverflow.com/questions/19233923/extending-class-at-runtime) – Theodore Murdock Apr 23 '14 at 19:45

4 Answers4

6

To reiterate what you are trying to do..

Within the JVM, there exists an instance of ClassA. You would like to dynamically modify the class heiarchy of ClassA, such that a new class exists called ClassB which derives from ClassA. Then you would like to instantiate an instance of ClassB but have it's subclass implementation be that of the existing instance of ClassA. Something like a memory replacement.

You might want to look into http://www.jboss.org/javassist . What you would need to do is replace the ClassLoader, then determine when ClassA is being loaded, then instantiated. You'd then need to construct ClassB and return that instead.

Update

After a little more research there is still the possibility you can do what you want. IDE's like Eclipse support HotSwap'ing method implementations while debugging. They use the Instrumentation API.

http://zeroturnaround.com/blog/reloading_java_classes_401_hotswap_jrebel/

You can replace method bodies but not add or remove methods themselves. So while you won't be able to change the type to your new type, you can completely replace the method implementation with your new implementation.

Andrew T Finnell
  • 13,417
  • 3
  • 33
  • 49
  • I am not changing inheritance at runtime, but only instantiating a subclass when its superclass is already instantiated. – JAKJ Apr 06 '12 at 16:26
  • @JAKJ The answer is still the same. You have an existing object that you want to Adapt into another type of object. IF you can control the initial return point of this new object then you can Adapt it and return the instance you want. I suggest you update your question with your Use Case not what you think the solution is. – Andrew T Finnell Apr 06 '12 at 16:28
  • I do not have the ability to replace the classloader as my class is loaded after the superclass nor can I use third-party runtimes. This must be within Java. – JAKJ Apr 06 '12 at 16:31
  • You are SOL then. If you can control the way the JVM starts you can do anything. If you cannot then you are stuck. What is the Use Case? Please update the original question with what you are needing to accomplish. – Andrew T Finnell Apr 06 '12 at 16:34
  • I do not have the option of having every end user install a debugging classloader, but I'll go ahead and accept this answer because it's the closest to a solution there seems to be. It appears that Java just is not capable of my desired behavior. – JAKJ Apr 06 '12 at 20:21
  • I was just looking into a solution to a similar project. It's unfortunate that we can't dynamically extend an instantiated class. – Salsero69 Dec 20 '17 at 21:00
3

I would suggest using cglib:

cglib is a powerful, high performance and quality Code Generation Library, It is used to extend JAVA classes and implements interfaces at runtime

You may find some examples here: https://github.com/cglib/cglib/wiki

Lefteris Laskaridis
  • 2,292
  • 2
  • 24
  • 38
2

Have you looked at Java Proxies?

Here is a snippet from Javadoc:

"A dynamic proxy class (simply referred to as a proxy class below) is a class that implements a list of interfaces specified at runtime when the class is created"

Alex Paransky
  • 295
  • 1
  • 3
  • 12
2

I don't know if it's a sollution but if you have

public static Foo foo = new Foo();

and you want to replace it with Bar which extends Foo make Bar an Wrapper for of Foo and use reflection to let foo point to your Bar instance.

public class Foo extends Bar {
  private bar; 
  public Foo(Bar oldInstance) {
     this.bar = oldInstance;
  }
}

and

// exception handling ommitted
public static void onStartup() {
   Class fooRefClass = FooRef.class;
   Field fooRef = fooRefClass.getDeclaredField("foo");

   Foo foo = (Foo)fooRef.get(null);
   Bar bar = new Bar(foo);
   fooRef.set(null, bar);

}

As told I don't know if this is possible in your case.

andih
  • 5,570
  • 3
  • 26
  • 36