关闭

Class 类加载器,内部类加载实验

1201人阅读 评论(0) 收藏 举报
分类:

最近实验通过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);
		}
	}
}







0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:576392次
    • 积分:7516
    • 等级:
    • 排名:第2871名
    • 原创:258篇
    • 转载:173篇
    • 译文:0篇
    • 评论:34条
    最新评论