最近实验通过jdk编译后的Class多出一个内部类class文件,美元$符号的class文件,如A.class ,A$B.class,加载A.class总是报错。
除了加载内部类方法,还有就是把class文件打包成jar,通过自定义URLClassLoader 加载jar文件,做类似与Osgi的工作。
通过类加载器,做一个动态加载模块的应用服务器。
通过网上找到代码例子改改后解决现在的问题。
Exception in thread "main" java.lang.LinkageError: loader constraint violation: when resolving method "com.lw.loader.TestClass$TestInnerClass.<init>(Lcom/lw/loader/TestClass;)V" the class loader (instance of com/lw/loader/DynamicClassLoader) of the current class, com/lw/loader/TestClass, and the class loader (instance of sun/misc/Launcher$AppClassLoader) for resolved class, com/lw/loader/TestClass$TestInnerClass, have different Class objects for the type tClass;)V used in the signature
at com.lw.loader.TestClass.<init>(TestClass.java:12)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:374)
at com.lw.loader.DynamicClassLoaderTest.main(DynamicClassLoaderTest.java:17)
类加载器 重写findClass,通过defineClass写入二进制定义Class类
package com.lw.loader;
import java.io.File;
import java.io.FileInputStream;
import java.util.Hashtable;
import java.util.jar.Manifest;
public class DynamicClassLoader extends ClassLoader {
private Manifest manifest;
private Hashtable<String, ClassInfo> classInfo = new Hashtable<String, ClassInfo>();
/**
* Provide delegation constructor
*/
DynamicClassLoader(ClassLoader parent) {
super(parent);
}
/**
* Same old ClassLoader constructor
*/
DynamicClassLoader() {
super();
}
private String getClassPath(String className) {
String relativeClassPath = className.replace('.', File.separatorChar) + ".class";
String classPath;
try {
classPath = ClassLoader.getSystemResource(relativeClassPath).toURI().getPath().substring(1);
System.out.println(classPath);
if ((new File(classPath)).exists())
return classPath;
} catch (java.net.URISyntaxException e) {
}
return null;
}
/**
* This is the method where the task of class loading is delegated to our custom loader.
*
* @param name the name of the class
* @return the resulting <code>Class</code> object
* @exception ClassNotFoundException if the class could not be found
*/
protected Class findClass(String name) throws ClassNotFoundException {
// get path of given class
String classPath = getClassPath(name);
if (classPath == null)
throw new ClassNotFoundException(name);
// get last modified time of class file
File f = new File(classPath);
long lastModified = f.lastModified();
// check if given class loaded already
ClassInfo loadedClassInfo = classInfo.get(name);
// if class loaded is the newest one, no need to reload it
if ((loadedClassInfo != null) && (loadedClassInfo.lastModified >= lastModified))
return loadedClassInfo.classType;
FileInputStream fi = null;
try {
fi = new FileInputStream(f);
byte[] classBytes = new byte[fi.available()];
fi.read(classBytes);
Class result = defineClass(name, classBytes, 0, classBytes.length);
classInfo.put(name, new ClassInfo(result, lastModified));
return result;
} catch (Exception e) {
// We could not find the class, so indicate the problem with an exception
e.printStackTrace();
throw new ClassNotFoundException(name);
} finally {
if (null != fi) {
try {
fi.close();
} catch (Exception e) {
}
}
}
}
}
ClassInfo 信息
package com.lw.loader;
public class ClassInfo {
public Class classType;
public long lastModified;
public ClassInfo(Class classType) {
this.classType = classType;
this.lastModified = -1;
}
public ClassInfo(Class classType, long lastModified) {
this.classType = classType;
this.lastModified = lastModified;
}
}
测试类
package com.lw.loader;
public class TestClass {
public class TestInnerClass {
public void printMessage() {
System.out.println("Test inner info");
}
}
public TestClass() {
TestInnerClass cls = new TestInnerClass();
}
public void printMessage() {
System.out.println("Test info changed");
}
}
测试方法
package com.lw.loader;
import java.lang.reflect.Method;
public class DynamicClassLoaderTest {
public static void main(String[] args) throws Exception {
while (true) {
DynamicClassLoader classLoader = new DynamicClassLoader();
// classLoader.findClass("com.lw.loader.TestClass$TestInnerClass");
Class c = classLoader.findClass("com.lw.loader.TestClass");
Method printMessage = c.getMethod("printMessage");
Object o = c.newInstance();
printMessage.invoke(o);
Thread.sleep(5000);
}
}
}