首页 > 代码库 > Java类加载与对象调用

Java类加载与对象调用

最近遇到一个问题:

1. 我的类A

2. ThreadB线程的类加载器ClassLoaderB没有加载权限

3. 使用另一个线程ThreadA的类加载器ClassLoaderA加载类A,创建对象a

4. 将a给线程ThreadB,然后调用其toString()方法

5. 发现调用的是类A的toString(),而不是Object的toString()


具体代码如下

import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.concurrent.CountDownLatch;


public class TestClassLoader {

	public static Object obj;
	
	public static void main(String[] args) {
		AClassLoader cl = new AClassLoader();
		cl.addURL("a.jar");
		final CountDownLatch cdl = new CountDownLatch(1);
		Thread t = new Thread(new Runnable(){

			@Override
			public void run() {
				try {
					Class<?> cls = Thread.currentThread().getContextClassLoader().loadClass("com.abcd.ABCD");
					try {
						obj = cls.newInstance();
						System.out.println("in : " + obj.toString());
						cdl.countDown();
					} catch (Exception e) {
						e.printStackTrace();
					}
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
			
		});
		t.setContextClassLoader(cl);
		t.start();
		try {
			cdl.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(obj);
		Class<?> cls = null;
		try {
			cls = Thread.currentThread().getContextClassLoader().loadClass("com.abcd.ABCD");
		} catch (ClassNotFoundException e1) {
			//出现ClassNotFoundException
			e1.printStackTrace();
		}
		try {
			obj = cls.newInstance();
			System.out.println("in : " + obj.toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}


class AClassLoader extends URLClassLoader{
	
	public AClassLoader(){
		super(new URL[0]);
	}
	
	public void addURL(String filePath){
		File file = new File(filePath);
		URI uri = file.toURI();
		try {
			addURL(uri.toURL());
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}
}

类ABCD的代码

import java.lang.System;
import java.lang.String;

public class ABCD{
	public ABCD(){
	}	

	@Override
	public String toString(){
		return "abcd";
	}
}

得出的结果是

in : abcd
abcd
java.lang.ClassNotFoundException: com.abcd.ABCD
	at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
	at TestClassLoader.main(TestClassLoader.java:46)
java.lang.NullPointerException
	at TestClassLoader.main(TestClassLoader.java:52)

得出结论:

类加载器只有在类加载时会起到指示安全域的作用,但对象一旦被创建后,可以调用其Object的@Override方法