java class loader #2
ClassLoader 2
// src/java/lang/ClassLoader.java
public abstract class ClassLoader {
/*
* The parent class loader for delegation.
*/
private ClassLoader parent;
protected synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// First, check if the class has already been loaded
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
// If still not found, then call findClass in order
// to find the class.
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
....
}
코드 4.
코드 4는 JDK1.3 ClassLoader 클래스로서 부모 클래스로더로부터 먼저 클래스 로딩을 요청하고, 그것이 실패할 경우에 직접 클래스를 로딩합니다. 여기서 부모 클래스가 어떻게 결정되는 지를 보면 JDK 1.3의 ClassLoader 클래스는 다음과 같은 두 개의 생성자를 갖고 있습니다.
protected ClassLoader(ClassLoader parent) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
this.parent = parent;
initialized = true;
}
protected ClassLoader() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
this.parent = getSystemClassLoader();
initialized = true;
}
코드 5.
코드 5를 보면, 부모 클래스로더를 지정하지 않을 경우에는 시스템 클래스로더를 부모 클래스로더로 지정하고 있습니다. 커스텀 클래스로더에서 부모 클래스로더를 지정하기 위해서는 코드 6과 같이 하면 됩니다.
public class JarFileClassLoader extends ClassLoader {
public JarFileClassLoader () {
super(JarFileClassLoader.class.getClassLoader());
// 다른 초기화 관련 사항
}
....
public Class findClass(String name) {
// 지정한 클래스를 찾는다.
}
}
코드 6.
모든 클래스는 그 클래스에 해당하는 Class 인스턴스를 가지고 있습니다. 그 Class 인스턴스의 getClassLoader() 메소드를 통해서 그 클래스를 로딩한 클래스로더를 구할 수 있습니다. 코드 6에서는 JarFileClassLoader 클래스를 로딩한 클래스로더를 JarFileClassLoader 클래스로더의 부모 클래스로더로 지정하는 것입니다.
JVM에서 부모 클래스로더를 갖지 않은 유일한 클래스로더는 부트스트랩 클래스로더로서 부트스트랩 클래스로더는 자바 런타임 라이브러리에 있는 클래스를 로딩하는 역할을 맡고 있으며, 항상 클래스로더 체인의 첫 번째에 해당합니다. Java에서는 같은 클래스일지라도다른 클래스로더에 의해서 로딩되었다면 다른 클래스로 구분이 됩니다.
Example
public class ToolsJarLoader extends URLClassLoader {
private static ToolsJarLoader mInstance;
public static ToolsJarLoader getInstance() {
if(mInstance == null) {
mInstance = new ToolsJarLoader(((URLClassLoader)ClassLoader.getSystemClassLoader()).getURLs());
}
return mInstance;
}
public ToolsJarLoader(URL[] urls) {
super(urls);
}
@Override
public void addURL(URL url) {
super.addURL(url);
}
public boolean isLoaded(URL url) {
URL[] urls = getURLs();
for(URL temp : urls) {
if(temp.equals(url)) {
return true;
}
}
return false;
}
}
코드 7.
코드 7은 원하는 클래스 및 jar를 런타임에 동적으로 로드하기 위한 클래스 로더이다. addURL을 통해 jar 및 클래스를 로딩한다.
URL jarUrl = new File(toolsJarPath).toURI().toURL();
if(!ToolsJarLoader.getInstance().isLoaded(jarUrl)) {
ToolsJarLoader.getInstance().addURL(jarUrl);
}
Class cls = ToolsJarLoader.getInstance().loadClass("package.ClassName");
Object obj = cls.getConstructor(String.class).newInstance(arg1);
Method method = obj.getClass().getMethod("methodName");
method.invoke(obj);
코드 8.
코드 8은 특정 위치에 있는 jar 및 클래스를 코드 7에 있는 클래스로더를 이용하여 런타임에 동적으로 로딩하도록 한다. 로딩 후 해당 클래스를 만든다.
References
[1] http://javacan.tistory.com/3
[2] http://blog.naver.com/PostView.nhn?blogId=choigohot&logNo=40192701035