본문 바로가기

프로그래밍/BCI

[Java] ASM ClassWriter options

ClassWriter options


메소드의 스택 맵 프레임의 계산은 간단하지 않다. 지역 변수나 오퍼랜드 스택도 마찬가지이다.


이를 자동을 계산하도록 하기 위한 ClassWriter의 옵션은 다음과 같다.


  • new ClassWriter(0)

    • 자동으로 계산되는 것이 없다.

    • 수동으로 모든 것을 계산해야 하기때문에 어려울 수 있지만, 효율적으로 만들 수 있는 여지도 있다.

  • new ClassWriter(ClassWriter.COMPUTE_MAXS)

    • 지역 변수 및 오퍼랜드 스택의 크기를 자동 계산한다.

    • 여전히 visitMaxs 메소드는 호출해 주어야 한다.

      • 호출 시 인자는 어떤 값이 되어도 상관 없다.

    • 스택 맵 프레임은 수동으로 계산해야 한다.

  • new ClassWriter(ClassWriter.COMPUTE_FRAMES)

    • 모든 것이 자동으로 계산된다.

    • visitFrame을 호출할 필요는 없지만, visitMaxs는 여전히 호출해 주어야 한다.

      • 호출 시 인자는 어떤 값이 되어도 상관없다.


이런 옵션을 사용하는 것이 편하긴 하지만 속도의 저하가 발생한다.


  • COMPUTE_MAXS

    • ClassWriter를 10% 느리게 만든다.

  • COMPUTE_FRAMES

    • 두 배 정도 느리다.


프레임의 계산을 수동으로 하기로 결정했다면, 프레임의 압축은 ClassWrite의 도움을 받을 수 있다. 압축되지 않은 프레임들을 visitFrame(F_NEW, nLocals, locals, nStack, stack) 메소드로 방문 하기만 하면 된다. nLocals, nStack은 로컬 변수들과 오퍼랜드 스택의 크기이고, locals와 stacks는 해당 타입을 요소로 가지는 배열이다.


하나 더 주의 할 점은, 프레임들을 자동으로 계산하기로 했다면, 주어진 두 클래스의 공통 super class를 계산하는 것이 필요할 수도 있다. 이는 기본적으로 ClassWriter의 getCommonSuperClass 메소드에 의해 계산된다. 해당 두 클래스를 JVM에 로딩하고, reflection API를 사용해 계산된다. 서로 참조하는 여러 클래스를 생성하는 경우 아직 존재하지 않는 클래스를 참조하여 문제가 될 수도 있다. 이런 경우, getCommonSuperClass를 재정의 해야할 수도 있다.