class 클래스 로딩
CLASSPATH에 없는 클래스 로딩
java.lang.reflect를 이용하면 우리가 원하는 클래스에 대한 invoke가 가능하다는 것은 알고 있을 것이다.
하지만 classpath에 등록안되어진 클래스들에 대해서는 어떻게 할 것인가?
일일이 사용자에게 클래스 패스를 설정하게 할수만은 없는 일 입니다.
보통의 엔진들을 보게 되면 install되어진 디렉토리의 위치만을 세팅하도록 하고 있다.
set JAVA_HOME 이라던지
set ANT_HOME 이라던지
쉘스크립트에 의하여 그러한 것들을 정의하여 java process를 띄우곤 하는데 그러면 내가 ant.jar등을 등록하지 않았음에도 불구하고 해당 애플리케이션들이 잘 작동하는 이유는 무엇일까요?
그건은 바로 ClassLoader에 숨겨져 있습니다.
아래에서 보여지는 샘플코드는 classpath 프로퍼티에 등록이 되어지지 않은 클래스들에 대한 조작을 할 것입니다.
그렇게 함으로서 우리들이 만든 애플리케이션이 별다른 클래스로딩 정책 없이도 작동이 될수 있습니다.
그러려면 또한 잘 알아야 하는것이 reflection API가 있습니다.
이 부분에서는 그러한 것을 생략하고 URLClassLoader를 이용하여 디렉토리나 jar파일을 등록하여 가져오는 방법을 설명하도록 하겠습니다.
ClassLoader클래스는 이미 1.0API부터 존재했으며 URLClassLoader는 1.2에 새롭게 추가된 클래스이다.
우리가 사용하는 파일시스템이 URL이란 이름하에 조작이 될 수 있다는 것을 우선 명심해주시기 바랍니다.
이유는 file:// 이란 URI를 사용하기 때문이다.
아래에서는 특정한 티렉토리 안의 jar 파일에 대한 class loading샘플을 보여줍니다.
import java.io.*;
import java.net.*;
public class ClassLoading {
public static void main(String [] args) throws Exception {
// Create a File object on the root of the directory containing the class file
File file =
new File("D:/_Develop/jmxSamples/customMBean/log4j-1.2.8.jar");
try {
// Convert File to a URL
URL url = file.toURL();
// file:/D:/_Develop/jmxSamples/customMBean/log4j-1.2.8.jar
URL[] urls = new URL[]{ url };
System.out.println(urls);
// Create a new class loader with the directory
ClassLoader cl = new URLClassLoader(urls);
System.out.println(cl);
// Load in the class; Logger.class should be located in
// the directory file:/D:/_Develop/jmxSamples/customMBean/log4j-1.2.8.jar
Class cls = cl.loadClass("org.apache.log4j.Logger");
System.out.println(cls);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e2) {
e2.printStackTrace();
}
}
}
위에서 보는 것처럼 디렉토리를 설정하거나 특정 jar 파일을 사용할 수 있도록 작성합니다.
특정파일이 가르키지 않으면 해당 디렉토리의 class파일들을 package형태로 참조하도록 할 수 있는데 해당 디렉토리에 대한 클래스 로딩 샘플을 아래와 같습니다.
import java.io.*;
import java.net.*;
public class ClassLoading {
//Create a File object on the root of the directory containing the class file
File file =
new File("D:/_CVSDevelop/jca_hello_adapter/build/classes");
try {
// Convert File to a URL
URL url = file.toURL();
// file:/D:/_CVSDevelop/jca_hello_adapter/build
URL[] urls = new URL[]{ url };
System.out.println(urls);
// Create a new class loader with the directory
ClassLoader cl = new URLClassLoader(urls);
System.out.println(cl);
// Load in the class; Test.class should be located in
// the directory //file:/D:/_CVSDevelop/jca_hello_adapter/build/classes/com/b//ea/jca/test/Test
Class cls = cl.loadClass("com.bea.jca.test.Test");
System.out.println(cls);
}catch (MalformedURLException e){
e.printStackTrace();
}catch (ClassNotFoundException e2){
e2.printStackTrace();
}
}
위와 같은 경우에는 classpath의 root로 잡은 디렉토리를 기준의 package형태로 설정되 파일을 로딩하여 사용할수 있도록 한다.
이 이후의 코딩에는 class가 newInstance를 취한 후 method를
invoking해야 하는 과정을 거치게 되는데 한 가지 주의할 점은 해당 클래스를 반드시 reflection API를 이용하여 호출해야 한다는 점이다.
대략 아래의 코드정도를 이용하여 main 메소드등을 호출하는 클래스를 작성할 수 있을 것이다.
public void invokeClass(String name, String[] args)
throws ClassNotFoundException, NoSuchMethodException,
InvocationTargetException
{
Class c = loadClass(name);
Method m = c.getMethod("main", new Class[] {args.getClass()});
m.setAccessible(true);
int mods = m.getModifiers();
if(m.getReturnType() != void.class || !Modifier.isStatic(mods) || !Modifier.isPublic(mods)){
throw new NoSuchMethodException("main");
}
try {
m.invoke(null, new Object[] { args });
}catch (IllegalAccessException e) {
// This should not happen, as we have disabled //access checks
}
}
위와 같은 샘플을 이용하게 되면 서버측 프로그램에 대한 작성을 해볼 수 있는 좋은 기회가 아닐까 생각 됩니다.
'JAVA' 카테고리의 다른 글
[JAVA]classes 위치 가져오기 (0) | 2017.10.30 |
---|---|
[JAVA] Class.forName 사용하기 (0) | 2017.10.30 |
[JAVA] class 동적로딩 (0) | 2017.10.30 |
[JAVA] class path에서 resource 찾기 (0) | 2017.10.30 |
[JAVA] cache function (0) | 2017.10.27 |