Runtime 에 jar 파일 클래스패스에 추가 시키기 : RuntimeJarLoader

자바로 만든 프로그램을 실행시킬때 java -classpath "jar 파일들 목록" "실행할 자바클래스" 요런식으로 프로그램에서 사용하는 jar 파일을

클래스패스에 추가시켜 줘야 된다.


그런데 톰캣같은 WAS 를 보면 WEB-INF\lib 폴더 아래에 있는 jar 파일들을 딱히 클래스패스에 추가시켜 주지 않아도 지가 알아서 클래스 패스에 추가시켜준다.


요런 기능과 비슷한일을 하는 클래스를 맨들어 보았다.
import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * 
 * @author stove99.tistory.com
 *
 */
public class RuntimeJarLoader {
	public static void loadJarIndDir(String dir){
		try{
			final URLClassLoader loader = (URLClassLoader)ClassLoader.getSystemClassLoader();
			final Method method = URLClassLoader.class
                                       .getDeclaredMethod("addURL", new Class[]{URL.class});
			method.setAccessible(true);
			
			new File(dir).listFiles(new FileFilter() {
				public boolean accept(File jar) {
					// jar 파일인 경우만 로딩
					if( jar.toString().toLowerCase().contains(".jar") ){
						try{
							// URLClassLoader.addURL(URL url) 메소드 호출
							method.invoke(loader, new Object[]{jar.toURI().toURL()});
							System.out.println(jar.getName()+ " is loaded.");
						}catch(Exception e){
							System.out.println(jar.getName()+ " can't load.");
						}
					}
					return false;
				}
			});
		}catch(Exception e){
			throw new RuntimeException(e);
		}
	}
}

RuntimeJarLoader.java



※ 코드 설명

일단 현재 실행중인 JVM 에 동적으로 jar 파일을 클래스 패스에 추가 시킬려면
요 코드로 시스템의 클래스 로더를 가져와야 한다.
URLClassLoader loader = (URLClassLoader)ClassLoader.getSystemClassLoader();

가져온 현재 JVM 의 클래스 로더를 이용하여 jar 파일을 로딩시켜 주면 되는데

문제는 jar 파일을 로딩시켜주는 일을 하는 메소드( URLClassLoader.addURL(URL url) )가 protected 라는 것이다.

그래서 loader.addURL("jar 파일"); 요런식으로 외부에서 직접 호출이 불가능 하다.



뭔가 이유가 있어서 protected 로 만들어 놨겠지만 나의 목표를 위해서는 꼭 저 addURL 메소드를 호출해야 할 필요가 있다.

아무튼 저 addURL 메소드를 호출하기 위한 방법으로 Java reflection 을 이용했다.

요코드로 호출할 메소드를 정의하고
Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});


핵심은 요부분이 되겠다. protected 로 선언된 메소드를 public 이로 바꿔주는 일을 한다. 요렇게 public 으로 바꿔준다음
method.setAccessible(true);


요런 Java reflection 코드를 이용해서 addURL() 을 호출해 주면, 바라던 Runtime 에 jar 파일을 클래스 패스에 추가시킬수 있다.
method.invoke(loader, new Object[]{jar.toURI().toURL()});



※ 참고 RuntimeJarLoader 사용법
// c:\lib 폴더 아래에 있는 jar 파일들 로딩
RuntimeJarLoader.loadJarInDir("c:/lib");

// 현재 실행중인 경로의 하위에 있는 lib 폴더 로딩
RuntimeJarLoader.loadJarInDir("./lib");

요렇게 쓰면 된다~