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

原创 2015年11月21日 15:03:19

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







版权声明:本文为博主原创文章,未经博主允许不得转载。

CGlib之LazyLoader实现延迟加载对象

一、延迟加载器LazyLoader作用:        说到延迟加载,应该经常接触到,尤其是使用Hibernate的时候,本篇将通过一个实例分析延迟加载的实现方式。LazyLoader接口继承了Ca...
  • zmx729618
  • zmx729618
  • 2016年11月14日 11:26
  • 534

内部类的加载时机

内部类是延时加载的,也就是说只会在第一次使用时加载。不使用就不加载,所以可以很好的实现单例模式。 package com.brouth.study.test; public class O...
  • brouth
  • brouth
  • 2016年06月13日 11:47
  • 2952

内部类加载顺序及静态内部类单例模式

加载一个类时,其内部类是否同时被加载?下面我们做一个实验来看一下。  Java代码   public class Outer {       static {     ...
  • zmx729618
  • zmx729618
  • 2017年04月05日 10:36
  • 1802

加载一个类时,其内部类是否同时被加载?静态内部类单例模式

加载一个类时,其内部类是否同时被加载?下面我们做一个实验来看一下。  Java代码   public class Outer {       static {       ...
  • Davidluo001
  • Davidluo001
  • 2015年12月04日 13:39
  • 4344

【J2SE】为什么静态内部类的单例可以实现延迟加载

为什么静态内部类的单例可以实现延迟加载
  • reliveIT
  • reliveIT
  • 2016年10月20日 19:21
  • 2646

内部类和外部类的使用规则

内部类的访问规则: 1,内部类可以直接访问外部类中的成员,包括私有。        之所以可以直接访问外部类中的成员,是内部类中持有了一个外部类的引用。格式:外部类名.this 2,...
  • Rainy_wupb
  • Rainy_wupb
  • 2016年05月04日 20:58
  • 1909

朝花夕拾——Java静态内部类加载

之前写《Java的synthetic修饰词》一文的过程中,提到了以下观点: 静态内部类不持有外部类的引用 这个观点是众所周知的。虽然明白是因为其构造函数内没有传入外部类的引用。可是为什么静态类可以...
  • u011435746
  • u011435746
  • 2015年12月18日 12:09
  • 3652

关于java内部类加载顺序的问题

前面是看到某个论坛讨论的内部类加载顺序的问题,链接如下:http://www.oschina.net/question/2273217_217864#tags_nav 今天看了单例模式,对内部类...
  • penker_zhao
  • penker_zhao
  • 2015年09月10日 23:43
  • 2536

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

JAVA class jvm
  • huaishu
  • huaishu
  • 2015年11月21日 15:03
  • 1571

利用自定义的 ClassLoader 加密 Java Class 文件

本文演示利用自定义的 ClassLoader 加密 Java Class 文件 首先,我们定义一个需要被加密的Java Class: classload.MyClassBase。 为了让客户端使用...
  • xidianliuy
  • xidianliuy
  • 2016年05月31日 11:58
  • 4586
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Class 类加载器,内部类加载实验
举报原因:
原因补充:

(最多只允许输入30个字)