Solved

Class loading

Posted on 2001-06-15
24
171 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
ID: 6194699
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
ID: 6194705
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
ID: 6194721
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
Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

 
LVL 7

Expert Comment

by:Sasha_Mapa
ID: 6195451
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
ID: 6195466
Yes that's a simpler solution, you are right. Without the thread spawning stuff.
0
 

Author Comment

by:shtern
ID: 6196656
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
ID: 6196722
// 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
ID: 6197108
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
ID: 6197115
Err, mainMethod should be invoked with realArgs, not args, sorry.

Sasha Maryanovsky.
0
 
LVL 3

Expert Comment

by:dnoelpp
ID: 6197872
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
ID: 6200089
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
ID: 6200091
Some ideas? It's really important for me!
0
 
LVL 7

Accepted Solution

by:
Sasha_Mapa earned 300 total points
ID: 6200154
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
ID: 6200308
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
ID: 6201969
Sorry, I'm not sure what you mean...

Sasha Maryanovsky.
0
 

Author Comment

by:shtern
ID: 6202339
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
ID: 6203706
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
ID: 6203771
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
ID: 6203889
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
ID: 6205263
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
ID: 6205274
Please look at AspectJ on the AOP page, too.
0
 
LVL 7

Expert Comment

by:Sasha_Mapa
ID: 6205367
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
ID: 6205378
Sasha, in this case bcel will be of help, what do you think?
0
 

Author Comment

by:shtern
ID: 6221133
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

Ransomware-A Revenue Bonanza for Service Providers

Ransomware – malware that gets on your customers’ computers, encrypts their data, and extorts a hefty ransom for the decryption keys – is a surging new threat.  The purpose of this eBook is to educate the reader about ransomware attacks.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:

777 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