2

I have made a custom class loader and I don't know how to "register" it.

public static void main( String[] args ) throws Exception {
   File            jar   = new File( "Simple.jar" );
   FileInputStream fis   = new FileInputStream( jar );
   byte[]          bytes = new byte[(int)jar.length()];
   fis.read( bytes );
   fis.close();
   MemoryClassLoader cl = new MemoryClassLoader();
   cl.defineClasses( bytes );

   // 1: Following lines works well
   cl.findClass ( "help.Simple" )
      .getMethod( "main", new Class[]{ String[].class })
         .invoke( null, (Object)args );

   // 1: it works well
   cl.findClass ( "help.Simple" )
      .getMethod( "main", new Class[]{ String[].class })
         .invoke( null, (Object)args );

   // 2: it works well too
   Class.forName( "help.Simple", true, cl )
      .getMethod( "main", new Class[]{ String[].class })
         .invoke( null, (Object)args );

   // 3: it doesn't work
   Class.forName( "help.Simple" )
      .getMethod( "main", new Class[]{ String[].class })
         .invoke( null, (Object)args );
}

The actual MemoryClassloader is more complex and not detailed here.

This program outputs:

Hello, world!
Hello, world!
Exception in thread "main" java.lang.ClassNotFoundException: help.Simple
   at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
   at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
   at java.security.AccessController.doPrivileged(Native Method)
   at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
   at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
   at java.lang.Class.forName0(Native Method)
   at java.lang.Class.forName(Class.java:186)
   at loader.MemoryClassLoader.main(MemoryClassLoader.java:76)

The lines "Hello, world!" is printed by help.Simple.main( String[] args ). The class help.Simple is correctly loaded by my class loader. But the third way of invoking it Class.forName() doesn't work. Why and how can I add the classes I load with my custom class loader to the list of the "standard" classes loaded by the default system class loader ?

Aerospace
  • 1,270
  • 12
  • 19
  • I don't think it sets the classloader for the thread, but it gives you a way to query it easily. So the intent is to be able to write: `Thread.currentThread().getContextClassLoader().findClass(...)`. – assylias Feb 15 '13 at 10:00

1 Answers1

3

Class.forName uses by default the classloader that has loaded the current class (the one containing your main method). I think the only way to have it work in this case is to use the overloaded method accepting another class loader.

It should work fine when used inside other classes that are themselves loaded by your classloader.

Class.forName( "help.Simple", true, cl )
Grim
  • 1,608
  • 9
  • 12
  • You're right but I wait another response. I amended my initial question with your suggestion – Aerospace Feb 15 '13 at 10:08
  • If you mean actually using your custom classloader as the default for your main application class, i think the only way is to load it at startup of the jvm - see http://stackoverflow.com/questions/3801714/how-to-set-my-custom-class-loader-to-be-the-default – Grim Feb 15 '13 at 10:22