프로그래밍을 하다보면 이미 존재하는 Jar 파일에서 다른 클래스 또는 Jar를 참조해야 할때가 있다.
가장 손쉽고 일반적인 방법은 시스템 환경변수로 해당 클래스 또는 Jar를 클래스패스를 추가해 주는 것이다.
하지만 여기서는 이를 프로그래밍을 통해 해결하는 방법을 제시하고자 한다.
이는 아주 특별한 경우이며 실제 프로그램을 하다가 얼마나 필요할 지는 모르겠다.
예를들어 어떤 배포 Version인 Executable Jar (A.jar)가 있다고 하자.
(A.jar는 어떤 database에 종속적이지 않은 Ansi SQL을 이용하며 구현되었다고 가정한다.)
A.jar 파일은 Vendor 별 JDBC specification에 따라 구현된 jdbc library를 사용할 것이며,
Jar 파일 내부에 MANIFEST.MF에 포함된 클래스패스에는 Oracle JDBC Library만을 사용할 수 있도록 되어있다고 가정하자.
추후 MS SQL Server를 사용할 일이 있어 MS JDBC Library를 추가할 필요가 있다면 어떻게 해야할까?..
시스템 환경변수를 이용하지 않는다고 하면 가장 일반적인 방법은 MANIFEST.MF에 MS JDBC Library를 추가하여 다시 Jar를 배포하는 것이다.
하지만 이렇게 할 경우 Library가 추가될 때 마다 jar를 Packaging 하여 새로 배포해야 한다는 불편함이 따른다.
여기서는, A.jar Executable 배포 시 미리 추후 클래스패스에 추가될 Library 들이 들어갈 directory를 생성해 놓고, 해당 library를 추가해 주기만 하면 classpath에 추가 될 수 있도록 프로그래밍 하는 방법을 제시한다.
- Library가 위치할 디렉토리: dynamic_lib
- 추가될 Library: sqljdbc4.jar
1. Java Reflection을 이용해서 URLClassLoader class의 addURL method를 call 하는 방법
URLClassLoader의 addURL method는 접근지정자가 protected로 되어있습니다.
classloader에 새로운 URL을 추가하는 것은 일반적으로 추상화에 위배되는 행위이며, 알 수 없는 문제가 발생될 수 있기에
정상적인 방법 이외에는 사용할 수 없도록 숨겨놓았습니다.
아래 코드는 Java Reflection을 이용하여 addURL method를 호출하고 있습니다.
다만, package 또는 상속받은 클래스 이외에서 접근을 할 수 있도록 하기위해서 setAccessible() method를 이용했습니다.
접근지정자를 수정하여 호출하는 것이기 때문에 특정한 환경하에서는 SecurityException이 발생될 수도 있으니, 사용에 유의해아 합니다.
public static void main(String[] args) {
File dir = new File("./ dynamic_lib");
File[] files = dir.listFiles();
if (files != null) {
// To add libraries to classpath dynamically, loading jar files in the ./ dynamic_lib directory.
for (File file : files) {
System.out.println("file URI: " + file.toURI().toURL());
Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
method.setAccessible(true);
method.invoke(ClassLoader.getSystemClassLoader(), new Object[] {file.toURI().toURL()});
}
}
}
2. URLClassLoader 를 상속하여 구현한 후, 상속클래스를 이용하여 classpath에 추가하는 방법.
// MyClassLoader which extends URLClassLoader class.
import java.net.URL;
import java.net.URLClassLoader;
public class MyClassLoader extends URLClassLoader {
/**
* @param urls, to carryforward the existing classpath.
*/
public MyClassLoader(URL[] urls) {
super(urls);
}
@Override
/**
* add ckasspath to the loader.
*/
public void addURL(URL url) {
super.addURL(url);
}
}
// Loading 방법
public static void main(String[] args) {
URLClassLoader loader = (URLClassLoader)ClassLoader.getSystemClassLoader();
MyClassLoader l = new MyClassLoader(loader.getURLs());
File dir = new File("./ dynamic_lib");
File[] files = dir.listFiles();
if (files != null) {
// To add libraries to classpath dynamically, loading jar files in the ./ dynamic_lib directory.
for (File file : files) {
System.out.println("file URI: " + file.toURI().toURL());
l.addURL(file.toURI().toURL());
}
}
}
'Language > Java' 카테고리의 다른 글
파일 인코딩 변환 프로그램 (0) | 2012.09.23 |
---|---|
[펌] JDBC performance tuning with optimal fetch size (0) | 2012.08.02 |
[펌] java.util.Timer의 schedule vs scheduleAtFixedRate (0) | 2012.07.29 |
Maven plugin - copy dependencies (0) | 2012.07.26 |
[펌] Add Oracle JDBC Jar to Maven Repository (0) | 2012.07.26 |