性能问答>关于不同虚拟机版本下的-XX:+TraceClassUnloading>
8回复
2年前

关于不同虚拟机版本下的-XX:+TraceClassUnloading


  1. 在JDK8中尝试重现类卸载的例子, 加入该参数并无法看到控制台有对应的unload日志输出(macos环境jdk1.8.0_161, linux环境jdk1.8.0_91均有尝试);
  2. 由于TraceClassUnloading在JDK9后不建议使用了, 被替换为了-Xlog:class+unload=info。 同样的代码在JDK9(macos环境make编译), JDK11下, 在新参数下, 均能看到对应的unload日志。形如
    [0.106s][info][class,unload] unloading class com.github.universe.java.base.Pow 0x0000000800060840
  3. 为何?

测试代码如下:

public class Loop {


	public static void main(String[] args) throws Exception{

		ClassLoaderB loaderB = new ClassLoaderB("CLB");
		loaderB.setPath("/Users/mozilla/core/universe/java-base/target/classes/");
		Class<?> clazz = loaderB.loadClass("com.github.universe.java.base.Pow");
		Object object = clazz.newInstance();
		System.out.println(object);

		System.out.println("-----------------");
		loaderB = null;
		clazz = null;
		object = null;

		System.gc();

		// System.gc();
		while (true){
			Thread.sleep(100000);
		}
	}

	private static class ClassLoaderA extends ClassLoader{}
	private static class ClassLoaderB extends ClassLoader {

		private String classLoaderName;

		//类的扩展名
		private final String fileExtension = ".class";

		private String path;

		public void setPath(String path) {
			this.path = path;
		}

		public ClassLoaderB(String classLoaderName) {
			super();
			this.classLoaderName = classLoaderName;
		}

		public ClassLoaderB(String classLoaderName, ClassLoader parent) {
			super(parent);
			this.classLoaderName = classLoaderName;
		}


		@Override
		protected Class<?> findClass(String className) throws ClassNotFoundException {
			System.out.println("findClass invoked: " + className);
			System.out.println("class loader name: " + this.classLoaderName);
			byte[] data = this.loadClassDate(className);
			return this.defineClass(className, data, 0, data.length);
		}

		private byte[] loadClassDate(String name) {
			InputStream is = null;
			byte[] data = null;
			ByteArrayOutputStream baos = null;

			try { 
				name = name.replace(".", "/");
				is = new FileInputStream(new File(this.path + name + this.fileExtension));
				baos = new ByteArrayOutputStream();

				int ch = 0;
				while ((ch = is.read()) != -1) {
					baos.write(ch);
				}
				data = baos.toByteArray();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					is.close();
					baos.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			return data;
		}
	}
}

5443 阅读
请先登录,再评论

Loop.class这个类的路径也在/Users/mozilla/core/universe/java-base/target/classes/?

2年前
回复 大空翼:

一语点醒梦中人。完全忽略了这里。当前的appclassloader的确包含了改地址。然后debug能看到cl的确是app。。 至于9和11的jdk是ok的是因为我恰好把目录隔开了。。 多谢

2年前回复
回复 Mozilla:

ClassLoader的委托类加载机制,并不一定是你指定的这个类加载器加载的,可能委托给父类加载器加载

2年前回复
回复 大空翼:

如果相同等于CL是活的, 确实不能unload。 但是如上所示, 代码了指明让ClassLoaderB去load。而且load成功后我也会打出log在console。而且同一份代码JDK8可以JDK9,11可以就很头疼了。

2年前回复
查看更多

厉害了

2年前