Link to home
Start Free TrialLog in
Avatar of shtern
shtern

asked on

Class loading

Hello!

Is there a possibility to set the own class loader for the whole application? I know about the possibility to do this for each case:

Object o = myClassLoader.LoadClass("Object").newInstance();

Could it be done for all classes without having to write it each time?

Thanx
Avatar of dnoelpp
dnoelpp
Flag of Switzerland image

You can't I am afraid. But you can set a context class loader for a thread.

Use: Thread.getCurrentThread().setContextClassLoader(myClassLoader);

Hope this partial solution helps you.

A workaround for the limitation that you can only set the class loader for a thread I suggest to do the following.

In the main() function of your application create a thread and set the class loader of this thread. Start this thread.
In this thread the first thing is to load the first class with the new class loader and invoke the application with it.

This is called boot strapping, I think so.
Like this:

// A function in the thread. When this function
// gets called, the new classloader is already set.

// Loads the class app.BootStrapper with a method boot()
// and invokes it.
public void run() {
    try {
        Object bootStrap = Class.forName("app.BootStrapper");
        Method boot = bootStrap.getClass().getMethod("boot", null);
        boot.invoke(bootStrap, null);
    } catch (Exception exc) {
        exc.printStackTrace();
    }
}
Avatar of Sasha_Mapa
Sasha_Mapa

Create a wrapper main method around your real main method. The wrapper main method would belong to a different class, it would load the real main class using your custom classloader and then invoke its main method. This will cause your main class, and thus all the other classes, to be loaded with your custom classloader.

Sasha Maryanovsky.
Yes that's a simpler solution, you are right. Without the thread spawning stuff.
Avatar of shtern

ASKER

Sasha,

could you please give me a short example, somehow I can't get it working.

Thank you.
// This is the wrapper class
package app;

public class Wrapper {
    public static void main(String[] args) {

        ClassLoader myClassLoader;
        // code here to define your custom class loader

        Thread.getCurrentThread().setContextClassLoader(myClassLoader);

        Application.main(args);
    }
}

*** ***

// This is your real main class
package app;

public class Application {
 
    // your stuff here

    static void main(String[] args) {
       // your stuff here
    }
}
dnoelpp, that's not quite what I meant. Here it is:

import java.reflect.*;

public class Wrapper{

  public static void main(String [] args) throws Exception{
    ClassLoader loader = new MyCustomClassLoader();
    Class appClass = loader.loadClass(args[0],true);
    String [] realArgs = new String[args.length-1];
    System.arraycopy(args,1,realArgs,0,realArgs.length);
    Method mainMethod = appClass.getMethod("main",(String[]).class);
    mainMethod.invoke(null,new Object[]{args});
  }

}


public class Application{

  static{
    System.out.println("Class Application loaded with "+Application.class.getClassLoader()+" classloader");
  }

  public static void main(String [] args){
    System.out.println("Main invoked");
  }

}


You would then run the program with "java Wrapper Application <the real arguments here>"

Sasha Maryanovsky.
Err, mainMethod should be invoked with realArgs, not args, sorry.

Sasha Maryanovsky.
Ah, that's sort of a generic wrapper utility... Good idea, this way you can wrap all applications that they use the new class loader.
Avatar of shtern

ASKER

Sorry, people,

I've tried your both examples, and they seem not to work. By testing which ClassLoader loads the Application I become sun.misc.Launcher$AppClassLoader@6f241 as a result.
Avatar of shtern

ASKER

Some ideas? It's really important for me!
ASKER CERTIFIED SOLUTION
Avatar of Sasha_Mapa
Sasha_Mapa

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of shtern

ASKER

Yes, you're right. Thank you very much. The points are already yours.

Just one more question: have you maybe tried to replace a class with another one while class loading? This another one extends that class. Is it possible at all?
Sorry, I'm not sure what you mean...

Sasha Maryanovsky.
Avatar of shtern

ASKER

I have to "wrap" the objects of my app with the ones which extend their functionality in some way. That's, for each class a wrapper class will be generated, which extends this class and adds something. Then, these classes must be used instead of the old ones. But it may not be programmed in the app itself, it should work with each app.
That's an interesting idea. Please tell us more about it. What functionality is put to the classes?
I think you should try adding methods to java.lang.Object in that case... If you want class specific information, you will need to modify the byte array you load for each class by adding methods to the class. To do that you need to learn the class file format, whose description is available at http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html

Sasha Maryanovsky.
Avatar of shtern

ASKER

dnoelpp,
what I have to do is "wrap" each class of my app, so that this wrapper adds some attributes to the class and overwrites each method so that there will be some action done and the method of superclass called.

Sasha, we've already tested in some way the idea with Object class and virtual machine modifying. What we want is that it works on each virtual machine and with each program without having to write it in some special way. We run first some art of "postcompiler" which generates these "wrappers" and then run our app with the custom classloader, which should replace old classes with wrappers. But until now I couldn't get it working. The main problem now: I can replace the class in class loader, but then the constructor can't be found.
Did you try bcel (http://bcel.sourceforge.net/), the ByteCode Engineering Library? They offer the possibility to modify class files during run time.

Another pointer: Aspect oriented programming. This is an extension of Java which allows to crosscut all classes of an application with some functionality. (http://www.parc.xerox.com/csl/projects/aop/)

Please look at AspectJ on the AOP page, too.
shtern, you need to do what I said my last comment - read it. Wrappers won't do it because you will be trying to load a class that the JVM didn't ask to load, this breaks the ClassLoader's contract.

Sasha Maryanovsky.
Sasha, in this case bcel will be of help, what do you think?
Avatar of shtern

ASKER

dnoelpp, I've looked at bcel. OK, the problem is I have to work the idea with classloading over. I may not just say: OK, we take bcel instead. I have to say: I've tried this and this. And it's not possible because...