Java, Reflection Tutorial - Dynamic Class Loading and Reloading. |
Java 에서 dynamic 하게 class 를 load 혹은 reload 할 수 있다.
The ClassLoader
Java 의 모든 class 는 ClassLoader의 subclass 를 이용하여 로드된다.
한 class 가 load 될 때 다른 연관된 ( refer 된 ) class 들도 모두 함께 recursive 하게 load 된다.
The ClassLoader Hierachy
새로운 class loader 를 작성할 떄면 반드시 Java 의 기본 ClassLoader 를 상속하여 이용해야 한다. 먼저 parent ClassLoader 를 이용하여 load 를 시도하고, parent 가 class 를 찾을 수 없다면, child class loader 가 load 를 시도하는 방식이다.
Class Loading
class loading 은 다음과 같은 절차로 이루어진다.
1. class 가 이미 load 되어 있는지 확인
2. 만약 load 안 되어있다면, parent class 에게 load 하도록 요구
3. parent class loader 가 해당 class 를 load 할 수 없다면, 자식 class 가 load 를 시도.
Dynamic Class Loading
class loading 은 ClassLoader 를 얻어서 loadClass() 를 호출하는 것 뿐이다.
ClassLoader classLoader = AClass.class.getClassLoader();
Class aClass = classLoader.loadClass( "com.example.AClass" );
Dynamic Class Reloading
Java 의 built in classloader 를 사용하면 reload 를 할 수 없다.
이유는 built in classloader 는 class 가 이미 load 되었는지 확인하기 때문.
만약 reload 를 하고자 하는 class loader 가 아닌 다른 class loader 에서 reload 를 하면, 이렇게 생성된 class들은 package name + class name 을 가지고 있더라도, ClassCastException 이 발생한다. 다른 녀석으로 간주하기 때문.
그래서 다음과 같은 방법으로 reloading 을 할 수 있다.
방법 1. variable type 으로 interface 를 사용하여 implementing 하며 reloading.
방법 2. superclass 를 variable type 으로 사용하여 바로 reload.
MyObject object = (MyObject) myClassReloadingFactory.newInstance( "com.example.MyObject" );
MyObjectInterface object = (MyObjectInterface) myClassReloadingFactory.newInstance( "com.example.MyObject" );
MyObjectSuperClass object = (MyObjectSuperClass) myClassReloadingFactory.newInstance( "com.example.MyObject" );
ClassLoader Load / Reload Example
public class MyClassLoader extends ClassLoader{
public MyClassLoader(ClassLoader parent) {
super(parent);
}
public Class loadClass(String name) throws ClassNotFoundException {
if( !"reflection.MyObject".equals( name ) )
return super.loadClass( name );
try {
String url = "file:C:/java/projects/classloader/classes/reflection/MyObject.class";
URL myUrl = new URL(url);
URLConnection connection = myUrl.openConnection();
InputStream input = connection.getInputStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int data = input.read();
while(data != -1){
buffer.write(data);
data = input.read();
}
input.close();
byte[] classData = buffer.toByteArray();
return defineClass("reflection.MyObject", classData, 0, classData.length);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
ClassLoader parentClassLoader = MyClassLoader.class.getClassLoader();
MyClassLoader classLoader = new MyClassLoader( parentClassLoader );
Class myObjectClass = classLoader.loadClass( "reflection.MyObject" );
AnInterface2 object1 = (AnInterface2) myObjectClass.newInstance();
MyObjectSuperClass object2 = (MyObjectSuperClass) myObjectClass.newInstance();
//create new class loader so classes can be reloaded.
classLoader = new MyClassLoader( parentClassLoader );
myObjectClass = classLoader.loadClass( "reflection.MyObject" );
object1 = (AnInterface2) myObjectClass.newInstance();
object2 = (MyObjectSuperClass) myObjectClass.newInstance();
}
public class MyObject extends MyObjectSuperClass implements AnInterface2{
//... body of class ... override superclass methods
// or implement interface methods
}
참고 사이트 : http://zeroturnaround.com/rebellabs/reloading-objects-classes-classloaders/
'프로그래밍 놀이터 > 안드로이드, Java' 카테고리의 다른 글
[Java] How to implements Iterator. (0) | 2014.01.10 |
---|---|
[android] 3D view 최적화. Droid Inspector. (7) | 2014.01.10 |
[android] CodePro Analytix 내 코드를 분석하자. (0) | 2014.01.09 |
[java] Decimal Pattern 특수문자. (0) | 2014.01.07 |
[android] ActionBarSherlock vs. ActionBar Compatibility (0) | 2014.01.07 |
댓글