์ด๋ฒ์๋ ์ด์ ์๊ฐ์ ๋ง๋ writeClass()๋ฅผ ์ด์ฉํด์ ์์ฑ๋ ํด๋์ค๋ฅผ ๋ณํ์ ํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
ํน์๋ "ํด๋์ค ์์ฑํ๊ธฐ" ์ฑํฐ๋ฅผ ๊ฑด๋๋ฐ์ ๋ถ๋ค์ ์ํด์ ์ ~~~~ ์๋์ชฝ์ writeClass() ๋ฉ์๋ ์์ค๋ฅผ ์ฌ๋ ค๋๋๋ก ํ๊ฒ ์ต๋๋ค.
์ ๊ทธ๋ผ ์์ํด๋ณผ๊น์...
๋ณํํ๋๊ฑฐ๋ ๊ทธ๋ฆฌ ์ด๋ ต์ง ์์ต๋๋ค. ClassVisitor๋ฅผ ์ด์ฉํ๋ฉด ๋ฉ๋๋ค. ์ ์ผ ์ฒซ๋ฒ์งธ ์๊ฐ์ MyClassVisitor๋ฅผ ๋ง๋ค์์ผ๋ ์ด๊ฑธ ์ด์ฉํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
ํฐ ๊ทธ๋ฆผ๋ถํฐ ํ๋ฒ ๋ณผ๊น์?? ์์๋ ์๋์ ๊ฐ์ต๋๋ค.
1. ClassWriter ์์ฑ
2. ClassWriter๋ฅผ ์ด์ฉํ์ฌ ClassVisitor ์์ฑ ( ClassWriter๋ฅผ ์ธ์๋ก ๋๊ฒจ์ค )
3. ClassReader๋ฅผ ์ด์ฉํ์ฌ ๋ณํํ๊ณ ์ํ๋ ํด๋์ค ์ ๋ณด๋ฅผ ์ฝ์ด๋ค์
4. cr.accept( ClassVisitor, int ) ๋ฉ์๋๋ฅผ ์ด์ฉํด์ ํด๋์ค ๋ณํ
์ค์ง์ ์ผ๋ก ๋ณํ์ ํ๋ ๋ ์์ ๋ฐ๋ก ์ด ClassVisitor๋ผ๋ ๊ฒ์ ์๊ณ ๋์ด๊ฐ์๋ฉด ๋ฉ๋๋ค.
์, ๊ทธ๋ผ ์ฐ์ ํด๋์ค๋ฅผ ๋ณํํ๊ธฐ์ํ ๋ฉ์๋๋ฅผ ํ๋ ๋ง๋ค์ด๋ณด์ฃ .
private byte[] transformClass(){
ClassWriter cw = new ClassWriter(0);
ClassVisitor cv = new MyClassVisitor(Opcodes.ASM5, cw){};
ClassReader cr = new ClassReader(writeClass());
cr.accept(cv, 0);
return cw.toByteArray();
}
์ฌ๊ธฐ์ writeClass()์ ์์ค๋ ์ด ํฌ์คํธ ํ๋จ์ ์์ต๋๋ค.
๊ฐ๋จํ๊ฒ ์์ค์ค๋ช ์ ๋๋ฆฌ์๋ฉด ์ฐ์ cw๋ฅผ ๋ง๋ค๊ณ cv๋ฅผ ์์ฑํ ๋ ์ธ์๋ก ๋ฃ์ด์ค๋๋ค. ์ฌ๊ธฐ์ ๊ธฐ์กด์ ๋ง๋ค์๋ MyClassVisitor์๋ ์ ์์ค์์ ์ฌ์ฉํ ์์ฑ์๊ฐ ์์ผ๋ฏ๋ก ํ๋๋ฅผ ์ถ๊ฐ๋ก ์์ฑํด์ฃผ์ ์ผ ํฉ๋๋ค.
MyClassVisitorํด๋์ค์ ์๋ ์์ฑ์๋ฅผ ํ๋ ์ถ๊ฐํด์ฃผ์ธ์.
public MyClassVisitor(int version, ClassWriter cw) {
super(version, cw);
}
๋ค์ ์์ค์ค๋ช ์ผ๋ก ๋์ด์์....
์ด๋ ๊ฒ cv๋ฅผ ์์ฑ์ ํ์ผ๋ฉด ์ด์ ๋ณํํ ํด๋์ค๋ฅผ ์ฝ์ด์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ cr์ accept()๋ฅผ ์ด์ฉํด์ ๋ฐฉ๋ฌธ(?)ํ๋ฉด์ ๋ณํ์ ํฉ๋๋ค. ์ด๋ ๊ฒ ๋ณํ์ด ๋ ํด๋์ค ์ ๋ณด๋ cw์ ๋ค์ด๊ฐ๊ฒ ๋ฉ๋๋ค.
๋ญ๊ฐ ๊ฐ๋จํ๊ฒ ๊ฐ์ผ๋ฉด์๋ ์ด์ง๋ฌ์ด๊ฒ ๊ฐ์ฃ ??
์, ๊ทธ๋ผ ํ ์คํธ๋ฅผ ํด๋ด์ผ ํ๊ฒ ์ฃ ..
์ฐ๋ฆฌ๊ฐ ๋ง๋ค์๋ MyClassVisitor์ visit() ๋ฉ์๋๋ฅผ ํ๋ฒ ๋ณผ๊น์?
@Override
public void visit(int version, int access, String name,
String signature, String superName, String[] interfaces) {
name = "BCItest/Modified";
super.visit(version, access, name, signature, superName, interfaces);
System.out.println(name + " extends " + superName + " {");
}
์, ์์์ ์ค๋ ์ง์์ผ๋ก ํ์๋ ๋ถ๋ถ์ด ์ถ๊ฐ๋ ๋ถ๋ถ์ ๋๋ค. ์ด๊ฒ ๋ญ ํ ๊ฑด์ง ์ง์์ด ๊ฐ์๋์?
์ ๊ทธ๋ฆฌ๊ณ ํ ์คํธ ํด๋์ค์์ ์ง๋ ์๊ฐ์ ํ๋ ์์ฑ๋ ํด๋์ค ํ ์คํธํด๋ณด๋ ์์ค๋ฅผ ์กฐ๊ธ๋ง ์์ ํด๋ณด๊ฒ ์ต๋๋ค.
// ๊ธฐ์กด ํ ์คํธ ์์ค
Class c = new MyClassLoader().defineClass("BCItest.Comparable", writeClass());
System.out.println(c.getName());
// ์์ ํ ํ ์คํธ ์์ค
Class c = new MyClassLoader().defineClass("BCItest.Comparable", transformClass());
System.out.println(c.getName());
๋ณ๊ฒฝ๋ ๋ถ๋ถ์ ์ค๋ ์ง์์ผ๋ก ํ์ํ์ต๋๋ค.
์ด๋ ๊ฒ ํด์ ์คํ์ ํ๋ฉด ๋ญ๊ฐ ๋์ฌ๊น์?
ClassLoader๋ก ์ฝ์ด์ค๋ ๊ณผ์ ์์ ์๋์ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฉ๋๋ค.
java.lang.NoClassDefFoundError: BCItest/Comparable (wrong name: BCItest/Modified)
์....์ฐ๋ฆฌ๊ฐ ํด๋์ค๋ก๋๋ฅผ ์ด์ฉํด์ ๋ก๋ํ๋ ค๊ณ ํ ํด๋์ค๋ช ์ Comparable์ด์๋๋ฐ transformClass()์์ ๋ง๋ค์ด์ง ํด๋์ค๋ Modified์ด๊ธฐ ๋๋ฌธ์ ๋๋ค.
๊ทธ๋ผ ์ด๋ฒ์๋ BCItest.Modified๋ฅผ ์ฝ์ด์ค๋๋ก ํด๋ด ์๋ค.
Class c = new MyClassLoader().defineClass("BCItest.Modified", transformClass());
์ ์ฒ๋ผ defineClass() ๋ฉ์๋์ ๋ค์ด๊ฐ๋ ์ธ์๋ฅผ ๋ฐ๊ฟ์ฃผ์ธ์.
์ด์ ๋ค์ ์คํํด๋ณด๋ฉด BCItest.Modified ๋ผ๊ณ ์ถ๋ ฅ์ด ๋๋ ๊ฒ์ ํ์ธํ์ค ์ ์์๊ฒ๋๋ค.
์ฐธ๊ณ ๋ก ์ง๋๋ฒ์ ํ๋ MyClassVisitor๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ์ ๋ค๋ฉด ํด๋์ค ๊ตฌ์กฐ๊ฐ ์ถ๋ ฅ๋๋ ๊ฒ๋ ๋ณด์ค ์๊ฐ ์์ต๋๋ค.
์ด๋ ต์ง ์์ฃ ?
์ ์ด์ ์ฌ๋ฌ๋ถ๋ BCI์ ๊ธฐ๋ณธ๊ธฐ๋ฅผ ๋ชจ๋ ์ตํ ์ ์ ๋๋ค.
ํด๋์ค ์ฝ๊ธฐ, ์ฐ๊ธฐ, ์์ ๊น์ง ํ์ผ๋๊น์.
ASM์ ์ด์ฉํด์ ํด๋์ค๋ฅผ ์ฝ์ด์ค๊ณ , ์์ฑ ๋ฐ ๋ณํํ๋ ๋ถ๋ถ๊น์ง ๊ณต๋ถ๋ฅผ ํด๋ณด์๋๋ฐ์
์ ๊ฐ ์ค๋ช ํ๋ ๋ฅ๋ ฅ์ด ์ฝํด์ ์ฒซ์๊ฐ๋ถํฐ ์ง๊ธ๊น์ง ํ ๋ด์ฉ์ ์์ค๋ฅผ ์ฒจ๋ถํ์ผ๋ ์์ค๋ฅผ ๋ณด๋ฉด์ ์ฒ์ฒํ ํ๋ฒ ๊ณต๋ถํด๋ณด์ธ์ ^_^
๋ค์์๊ฐ์๋ ์์ ํ ๋ ์ต์ ํ ๊ด๋ จ๋ ๋ถ๋ถ์ ๋ํด์ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
๊ทธ๋ผ ์ฌ๋ฌ๋ถ ์๋
~์~
์ถ์ฒ : ASM 4 ๊ฐ์ด๋ ๋ฌธ์
-----------------writeClass()-----------------------
BCItest ํจํค์ง๋ฅผ ๊ธฐ์ค์ผ๋ก ์์ค๊ฐ ์์ฑ๋์์ต๋๋ค.
private byte[] writeClass(){
ClassWriter cw = new ClassWriter(0);
cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT + Opcodes.ACC_INTERFACE,
"BCItest/Comparable", null, "java/lang/Object",
null);
cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "LESS", "I",
null, new Integer(-1)).visitEnd();
cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "EQUAL", "I",
null, new Integer(0)).visitEnd();
cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "GREATER", "I",
null, new Integer(1)).visitEnd();
cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "compareTo",
"(Ljava/lang/Object;)I", null, null).visitEnd();
cw.visitEnd();
return cw.toByteArray();
}
'๐ป Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android/์๋๋ก์ด๋] Fragment ์ฌ์ฉํ๊ธฐ (0) | 2015.08.15 |
---|---|
[์๋๋ก์ด๋] View.INVISIBLE vs. View.GONE ( INVISIBLE๊ณผ GONE์ ์ฐจ์ด์ ) (0) | 2015.08.01 |
[ASM 5.0] 2. BCI๋ฅผ ์ด์ฉํ ํด๋์ค ์์ฑํ๊ธฐ (0) | 2015.07.31 |
[ASM 5.0] 1. BCI๋ฅผ ์ด์ฉํ ํด๋์ค ํ์ผ ์ฝ๊ธฐ (0) | 2015.07.31 |
libGDX ๋ฅผ ์ด์ฉํ ๊ฒ์ ๊ฐ๋ฐ ์ ๋ฆฌ 3 - ์ผ๋ฆญํฐ ์์ง์ ๋ณด์ ํ๊ธฐ (0) | 2015.07.29 |