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

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

 

 

 

 

 

 

 

 


 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值