Re: alternative to my ClassLoader hack



Steven Simpson wrote:

public class MyClassLoader {
public static void main(String... args) throws Exception {
// Using subdir of current directory as example.
File curDir = new File(System.getProperty("user.dir"));
curDir = new File(curDir, "subdir").getCanonicalFile();
URL[] urls = { curDir.toURI().toURL() };

ClassLoader cl = new URLClassLoader(urls);
Class<?> main = Class.forName("TheRealMainClass", true, cl);

Method mth = main.getMethod("main", args.getClass());
mth.invoke(null, (Object[]) args);
}
}


Just for the record, this runs, but gets an exception. I'm not sure 100% why. I'll try to clean it up then make it use your method. The code below must be executed as a jar file or it won't reproduce the error.

$ java -jar test.jar
String name: /fubar/MyClassLoader.class
URL: jar:file:/C:/Users/Brenden/Dev/misc/fubar/build/classes/test.jar!/fubar/MyClassLoader.class
path to jar file:/C:/Users/Brenden/Dev/misc/fubar/build/classes/test.jar
making FubarLoader:
Classloader: fubar.FubarLoader@addbf1
finding fubar.Launcher
trying super class...
findClass got it
Exception in thread "main" java.lang.IllegalAccessException: Class fubar.MyClass
Loader can not access a member of class fubar.Launcher with modifiers ""
at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at fubar.MyClassLoader.main(MyClassLoader.java:53)

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package fubar;

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;


public class MyClassLoader
{
public static void main( String... args )
throws ClassNotFoundException, InstantiationException,
IllegalAccessException, MalformedURLException
{

URL[] urls = new URL[1];

String classResource = "/" +
MyClassLoader.class.getName().replaceAll( "\\.", "/" )
+ ".class";
System.out.println( "String name: " + classResource );
URL myClass =
MyClassLoader.class.getResource( classResource );

System.out.println( "URL: " + myClass );

String pathToClass = myClass.toString();
int index = pathToClass.indexOf( '!' );
pathToClass = pathToClass.substring( 4, index );
System.out.println( "path to jar " + pathToClass );
URL jarURL = new URL( pathToClass );

urls[0] = jarURL;

System.out.println( "making FubarLoader:" );
URLClassLoader cl = new FubarLoader( urls );
System.out.println( "Classloader: " + cl );
@SuppressWarnings( "unchecked" )
Class<Launcher> main = (Class<Launcher>) cl.loadClass(
"fubar.Launcher" );
Launcher mcl = main.newInstance();
mcl.launch();
}

private void startApplication( Class<?> c )
{
System.out.println( "Class files are equal: " + (c ==
MyClassLoader.class) );
System.out.println( "Classloader: " + getClass().
getClassLoader() );
// everything else here
}
}

class Launcher
{
public void launch()
{
System.out.println( "Classloader: " + getClass().
getClassLoader() );
}
}

/*
* classloader call trace:
*
* I. loadClass( String )
*
* II. loadClass( String, false )
* 3. findLoadedClass prot
* A. FindLoadClass0 -- native -- PRIVATE
* 4. loadClass (String) on parent
* 5. findBootstrapClass0 PRIVATE
* 6. findClass prot
* 7. resolveClass prot
* A. resolveClass -- native -- PRIVATE
*
*/

class FubarLoader extends URLClassLoader {

public FubarLoader( URL[] urls )
{
super( urls );
}

@Override
public Class<?> loadClass( String className )
throws ClassNotFoundException
{
if( className.startsWith( "fubar" ) ) {
System.out.println( "finding " + className );
Class<?> c = null;
try {
c = findClass( className );
}
catch( ClassNotFoundException ex ) {
}
if( c != null ) {
System.out.println( "findClass got it" );
return c;
}
}
System.out.println( "trying super class..." );
return super.loadClass( className );
}
}
.



Relevant Pages