问题描述:

I am getting java.lang.ClassCastException: CustomloaderDependency cannot be cast to CustomloaderDependency I know reason is two classes are loaded by different classloaders(one by customclassloader and another by default sun.misc.Launcher$AppClassLoader)

My custom class loader is not being used even after running the program with -Djava.system.class.loader=CustomClassLoader until and unless i am not explicitly doing Class.forName("CustomloaderDependency", true, ClassLoader.getSystemClassLoader() ); but when i do new CustomloaderDependency() default sun.misc.Launcher$AppClassLoader is used

Here is my custom class loader

 public class CustomClassLoader extends ClassLoader {

public CustomClassLoader() {

super();

}

/**

* This constructor is used to set the parent ClassLoader

*/

public CustomClassLoader(ClassLoader parent) {

super(parent);

}

/**

* Loads the class from the file system. The class file should be located in

* the file system. The name should be relative to get the file location

*

* @param name

* Fully Classified name of class, for example com.journaldev.Foo

*/

private Class getClass(String name) throws ClassNotFoundException {

String file = name + ".class";

byte[] b = null;

try {

// This loads the byte code data from the file

b = loadClassFileData(file);

// defineClass is inherited from the ClassLoader class

// that converts byte array into a Class. defineClass is Final

// so we cannot override it

Class c = defineClass(name, b, 0, b.length);

resolveClass(c);

return c;

} catch (IOException e) {

e.printStackTrace();

return null;

}

}

/**

* Every request for a class passes through this method. If the class is in

* com.journaldev package, we will use this classloader or else delegate the

* request to parent classloader.

*

*

* @param name

* Full class name

*/

@Override

public Class loadClass(String name) throws ClassNotFoundException {

System.out.println("Loading Class '" + name + "'" );

if (name.contains("CustomloaderDependency") || name.contains("TestCustomLoader")) {

System.out.println("Loading Class using CustomClassLoader");

return getClass(name);

}

return super.loadClass(name);

}

/**

* Reads the file (.class) into a byte array. The file should be

* accessible as a resource and make sure that its not in Classpath to avoid

* any confusion.

*

* @param name

* File name

* @return Byte array read from the file

* @throws IOException

* if any exception comes in reading the file

*/

private byte[] loadClassFileData(String name) throws IOException {

/*InputStream stream = ClassLoader.getSystemClassLoader().getResourceAsStream(

name);*/

// FileInputStream stream = new FileInputStream("F:\\workspaces\\test\\Test\\bin\\"+name);

FileInputStream stream = new FileInputStream("F:\\"+name);

int size = stream.available();

byte buff[] = new byte[size];

//DataInputStream in = new DataInputStream(stream);

stream.read(buff);

stream.close();

return buff;

}

}

Here is my testing class

I am running this program with -Djava.system.class.loader=CustomClassLoader but still looks like default class loader is used for classes with which i am trying to downcast with

 public class TestCustomLoader {

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {

Class classObject = Class.forName("CustomloaderDependency", true, ClassLoader.getSystemClassLoader() );

Object customloaderDependency = classObject.newInstance();

System.out.println("classloader from my custom is "+customloaderDependency.getClass().getClassLoader());

// above prints [email protected]

System.out.println("classloader for casting is "+CustomloaderDependency.class.getClassLoader());

// above prints [email protected]

CustomloaderDependency finalObject = (CustomloaderDependency)customloaderDependency;

//above line i am getting exception

}

网友答案:

I got it work by

  @Override
    public Class loadClass(String name) throws ClassNotFoundException {
        System.out.println("Loading Class '" + name + "'" );
        if (name.contains("CustomloaderDependency") || name.contains("TestCustomLoader")) {
            System.out.println("Loading Class using CustomClassLoader");
            return getClass(name);
        }
        return super.loadClass(name);
    }

Before above fix, call was coming to my customclassloader to load TestCustomLoader but i was loading it through Launcher$AppClassLoader because of if (name.contains("CustomloaderDependency") ) {.

Hence all it dependents(like statically mentioned class i.e the word in the cast parentheses) were also being loaded by Launcher$AppClassLoader

相关阅读:
Top