Solved

Class loading

Posted on 2001-06-15
24
169 Views
Last Modified: 2013-11-23
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
0
Comment
Question by:shtern
  • 10
  • 7
  • 7
24 Comments
 
LVL 3

Expert Comment

by:dnoelpp
Comment Utility
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.

0
 
LVL 3

Expert Comment

by:dnoelpp
Comment Utility
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.
0
 
LVL 3

Expert Comment

by:dnoelpp
Comment Utility
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();
    }
}
0
 
LVL 7

Expert Comment

by:Sasha_Mapa
Comment Utility
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.
0
 
LVL 3

Expert Comment

by:dnoelpp
Comment Utility
Yes that's a simpler solution, you are right. Without the thread spawning stuff.
0
 

Author Comment

by:shtern
Comment Utility
Sasha,

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

Thank you.
0
 
LVL 3

Expert Comment

by:dnoelpp
Comment Utility
// 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
    }
}
0
 
LVL 7

Expert Comment

by:Sasha_Mapa
Comment Utility
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.
0
 
LVL 7

Expert Comment

by:Sasha_Mapa
Comment Utility
Err, mainMethod should be invoked with realArgs, not args, sorry.

Sasha Maryanovsky.
0
 
LVL 3

Expert Comment

by:dnoelpp
Comment Utility
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.
0
 

Author Comment

by:shtern
Comment Utility
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.
0
 

Author Comment

by:shtern
Comment Utility
Some ideas? It's really important for me!
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 7

Accepted Solution

by:
Sasha_Mapa earned 300 total points
Comment Utility
This works for me:

import java.lang.reflect.*;
import java.io.*;

public class Wrapper{

  public static void main(String [] args) throws Exception{
    MyCustomClassLoader 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",new Class[]{String [].class});
    mainMethod.invoke(null,new Object[]{args});
 }

}


class MyCustomClassLoader extends ClassLoader{


  private byte [] loadClassData(String name) throws IOException{
    System.out.println(name.replace('.',File.separatorChar)+".class");
    InputStream in = new FileInputStream(name.replace('.',File.separatorChar)+".class");
    ByteArrayOutputStream buf = new ByteArrayOutputStream();
    int b;
    while ((b=in.read())!=-1){
      buf.write(b);
    }
    return buf.toByteArray();
  }


  public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException{
    byte data [];
    try{
      data = loadClassData(name);
    } catch (IOException e){
        return findSystemClass(name);
      }
    Class c = defineClass(data, 0, data.length);
    if (resolve)
      resolveClass(c);
    return c;
  }

}



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");
 }

}


What you must have done wrong is first trying to use ClassLoader.findSystemClass() and only then your way of loading. Since your class is probably in the classpath, the bootstrap classloader will have no problem loading it...

Sasha Maryanovsky.

0
 

Author Comment

by:shtern
Comment Utility
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?
0
 
LVL 7

Expert Comment

by:Sasha_Mapa
Comment Utility
Sorry, I'm not sure what you mean...

Sasha Maryanovsky.
0
 

Author Comment

by:shtern
Comment Utility
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.
0
 
LVL 3

Expert Comment

by:dnoelpp
Comment Utility
That's an interesting idea. Please tell us more about it. What functionality is put to the classes?
0
 
LVL 7

Expert Comment

by:Sasha_Mapa
Comment Utility
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.
0
 

Author Comment

by:shtern
Comment Utility
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.
0
 
LVL 3

Expert Comment

by:dnoelpp
Comment Utility
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/)

0
 
LVL 3

Expert Comment

by:dnoelpp
Comment Utility
Please look at AspectJ on the AOP page, too.
0
 
LVL 7

Expert Comment

by:Sasha_Mapa
Comment Utility
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.
0
 
LVL 3

Expert Comment

by:dnoelpp
Comment Utility
Sasha, in this case bcel will be of help, what do you think?
0
 

Author Comment

by:shtern
Comment Utility
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...
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
Viewers learn about the “while” loop and how to utilize it correctly in Java. Additionally, viewers begin exploring how to include conditional statements within a while loop and avoid an endless loop. Define While Loop: Basic Example: Explanatio…
This video teaches viewers about errors in exception handling.

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now