'Obfuscation'에 해당되는 글 1건

  1. 2007.09.02 Java Enum Type, Obfuscation Problem 2
자바2007. 9. 2. 16:00

Java enum type은 obfuscate할 때 주의가 필요하다. java.lang.Class.getEnumConstants()에서 reflection으로 해당 enum type의 'values'라는 메서드를 참조하기 때문이다.

예를 들어 net.rb.lab.TestEnum이라는 java enum type이 다음과 같은 소스코드를 가진다고 하자.

package net.rb.lab;

public enum TestEnum {

    ITEM_A,
    ITEM_B;
    
}

이 소스코드를 compile하면 다음과 같은 byte code outline을 확인할 수 있다.

net.rb.lab.TestEnum
Fields:
    ITEM_A
    ITEM_B
    ENUM$VALUES
Methods:
    <clinit>
    <init>
    values
    valueOf

실제 byte code를 decompile해보면 대략 아래와 같은 코드를 유추해낼 수 있다.
(아래 소스코드는 byte code의 구조파악을 위해 기술된 내용이고, Enum 상속 문제때문에 실제 complie은 안된다.)

package net.rb.lab;

public final class TestEnum extends Enum {

    public static final TestEnum ITEM_A;
    public static final TestEnum ITEM_B;
    private static final TestEnum[] ENUM$VALUES;

    static {
        ITEM_A = new TestEnum("ITEM_A", 0);
        ITEM_B = new TestEnum("ITEM_B", 1);
        ENUM$VALUES = new TestEnum[] { ITEM_A, ITEM_B };
    }
    
    private TestEnum(String name, int ordinal) {
        super(name, ordinal);
    }

    public static TestEnum[] values() {
        TestEnum[] newArray = new TestEnum[ENUM$VALUES.length];
        System.arraycopy(ENUM$VALUES, 0, newArray, 0, ENUM$VALUES.length);
        return newArray;
    }

    public static TestEnum valueOf(String name) {
        return (TestEnum) Enum.valueOf(TestEnum.class, name);
    }

}

보시다시피 enum type의 경우, Java compiler에 의해서 다음과 같이 두 메서드가 자동으로 생성된다.

  • public static TestEnum[] values()
  • public static TestEnum valueOf(String)

이 두 메서드가 바로 문제의 녀석들이다. TestEnum.valueOf(String) 호출은 결국 Class.getEnumConstants() 호출을 야기하는데, 만약 values() 메서드가 obfuscate되었다면 Class.getEnumConstants()는 reflection으로 해당 메서드를 찾을 수 없으므로 null을 return, 결국 JVM은 'TestEnum은 enum type이 아닐세'라며 exception을 던져버린다.

Obfuscation의 목적은 decompile시 의미파악을 어렵게 하기 위함인데, Java enum type의 'values'나 'valueOf'같은 메서드는 이미 공개된 내용이므로 obfuscation 목록에서 제외하는게 문제를 예방하는 데 도움이 될 것 같다.

Posted by roguebean