์˜ค๋Š˜์€ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ด๋ณด๋Š” ์˜ˆ์ œ๋ฅผ ๊ฐ€์ ธ์™€๋ดค์Šต๋‹ˆ๋‹ค.


ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ• ๋•Œ๋Š” ClassWriter ์ปดํฌ๋„ŒํŠธ๋งŒ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.


์ž, ์•„๋ž˜์™€ ๊ฐ™์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ClassWriter๋ฅผ ์ด์šฉํ•ด์„œ ์ƒ์„ฑํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.


:: ์ƒ์„ฑํ•˜๋ ค๋Š” ์ธํ„ฐํŽ˜์ด์Šค

package BCItest;
public interface Comparable extends Mesurable {
    int LESS = -1;
    int EQUAL = 0;
    int GREATER = 1;
    int compareTo(Object o);
}


-- ์œ„ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ์œ„ํ•œ ์†Œ์Šค

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",
        new String[] { "BCItest/Mesurable" });
        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();
}


๊ฐ„ ๋‹จํ•˜๊ฒŒ ์†Œ์Šค๋ฅผ ํ›‘์–ด๋ณผ๊นŒ์š”?? ์šฐ์„  ClassWriter ( ์ดํ•˜ cw ) ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  visit, visitField, visitMethod ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๋’ค์— ๋งˆ์ง€๋ง‰์œผ๋กœ visitEnd๋ฅผ ํ˜ธ์ถœํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ๋ฉ”์†Œ๋“œ์•ˆ์— ๋“ค์–ด๊ฐ€๋Š” ACC_XXX๋ผ๋Š” ์ƒ์ˆ˜๋“ค์€ ASM์— ๋ฏธ๋ฆฌ ์ •์˜๋˜์–ด์žˆ๋Š” Opcodes ๋“ค์ž…๋‹ˆ๋‹ค. Opcodes ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด์„œ ์‚ฌ์šฉํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


ํ•„ ๋“œ ์„ ์–ธ๋ถ€๋ฅผ ๋ณด์‹œ๋ฉด ์ฒซ๋ฒˆ์งธ ํ•„๋“œ๊ฐ€ int LESS ๋ผ๋Š” ํ•„๋“œ์ฃ . ์šฐ์„  ์ธํ„ฐํŽ˜์ด์Šค ๋‚ด์— ์„ ์–ธ๋˜์–ด์žˆ๋Š” int๋ผ์„œ visitField๋ฉ”์†Œ๋“œ์—์„œ public, final, static์ด๋ผ๋Š” ์ƒ์ˆ˜๊ฐ’์„ ์ฃผ๊ณ  ๊ทธ ๋‹ค์Œ์— ํ•„๋“œ๋ช…(LESS)๊ณผ ํ•„๋“œ ํƒ€์ž…(I)์„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋‹ค์Œ์— null์€ generic๊ด€๋ จ ํ•„๋“œ์ž…๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ๋Š” ํ•ด๋‹น ํ•„๋“œ์— ํ• ๋‹นํ•  ๊ฐ’์ž…๋‹ˆ๋‹ค. ์œ„ ์˜ˆ์ œ์—์„œ๋Š” new Integer(-1)์ด์ฃ . 


๊ทธ๋ฆฌ๊ณ  cw๋ฅผ ๋ฐ”์ดํŠธํ˜•ํƒœ๋กœ ์ถ”์ถœํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ์ด ๋ฐ”์ดํŠธ ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•ด์„œ ์ƒ์„ฑ๋œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•ด๋ณผ๊นŒ์š”??


์šฐ์„  ํด๋ž˜์Šค๋กœ๋”๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์ด MyClassLoader ํด๋ž˜์Šค๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”.

class MyClassLoader extends ClassLoader {
    public Class defineClass(String name, byte[] b) {
        return defineClass(name, b, 0, b.length);
    }   
}


๊ทธ๋ฆฌ๊ณ  ์•„๋ž˜์ฒ˜๋Ÿผ ํ…Œ์ŠคํŠธํ•ด๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค.


Class c = new MyClassLoader().defineClass("BCItest.Comparable", writeClass());
System.out.println(c.getName());


๋ฌธ์ œ๊ฐ€ ์—†๋‹ค๋ฉด BCItest.Comparable ์ด๋ผ๊ณ  ์ฝ˜์†”์ฐฝ์— ์ถœ๋ ฅ์ด ๋ ๊ฒ๋‹ˆ๋‹ค.

์—ฌ ๊ธฐ์„œ ์ž ๊น!!! ์ œ๊ฐ€ ์‹ค์Šตํ•ด๋ณธ ๊ฒฐ๊ณผ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ Mesurable์„ ์ƒ์†ํ•˜๋Š” ํ˜•ํƒœ๋กœ ๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์— Measurableํด๋ž˜์Šค๊ฐ€ ์—†๋‹ค๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋‚ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ 1. Measurable์„ ์ƒ์„ฑํ•ด ์ฃผ์‹œ๊ฑฐ๋‚˜ ์•„๋‹ˆ๋ฉด 2. writeClass()์˜ cw.visit() ๋ฉ”์†Œ๋“œ์˜ ๋งˆ์ง€๋ง‰ ์ธ์ž์ธ new String[] { " .... "} ๋ฅผ null ๋กœ ๋ฐ”๊ฟ”์ฃผ์‹œ๋ฉด ์‹คํ–‰์ด ์ž˜ ๋ ๊ฒ๋‹ˆ๋‹ค.



๊ทธ๋Ÿผ ๋‹ค์Œ ์‹œ๊ฐ„์—๋Š” ํด๋ž˜์Šค ๋ณ€ํ™˜์— ๋Œ€ํ•ด์„œ ์˜ฌ๋ฆฌ๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.







์ถœ์ฒ˜ : ASM ๊ฐ€์ด๋“œ