본문 바로가기

기술스택/ASM - [Bytecode]

[A Java bytecode engineering library] 1. Introduction

목차

    1.1. Motivations

     

    프로그램 분석, 생성 및 변환은 다양한 상황에서 유용하게 사용될 수 있는 기술이다.

     

    • 프로그램 분석은 간단한 구문 분석부터 전체 의미 분석에 이르기까지 다양하며, 응용 프로그램에서 잠재적인 버그를 찾거나 사용되지 않는 코드를 탐지하고, 코드를 역공학하는 데 사용될 수 있다.

    • 프로그램 생성은 컴파일러에서 사용되며, 이는 전통적인 컴파일러뿐만 아니라 분산 프로그래밍을 위한 스텁 또는 스켈레톤 컴파일러, 실시간 컴파일러 등을 포함한다.

    • 프로그램 변환은 프로그램을 최적화하거나 난독화하고, 응용 프로그램에 디버깅 또는 성능 모니터링 코드를 삽입하며, 관점 지향 프로그래밍 등에 사용될 수 있다. 이러한 기술들은 모든 프로그래밍 언어에 사용될 수 있지만, 언어에 따라 수행하기가 더 쉽거나 어려울 수 있다.

     

    Java의 경우, Java 소스 코드 또는 컴파일된 Java 클래스에 사용될 수 있다.

    컴파일된 클래스에서 작업하는 한 가지 장점은 소스 코드가 필요하지 않다는 것이다. 따라서 프로그램 변환은 폐쇄 소스 및 상업적 애플리케이션을 포함한 모든 애플리케이션에서 사용될 수 있다.

     

    컴파일된 코드에서 작업하는 또 다른 장점은, Java 가상 머신에 로드되기 직전에 클래스를 분석, 생성 또는 변환할 수 있다는 것이다(실시간으로 소스 코드를 생성하고 컴파일하는 것은 가능하지만 매우 느리고 전체 Java 컴파일러가 필요하다).

     

    이 장점은 스텁 컴파일러나 관점 직조기와 같은 도구를 사용자에게 투명하게 만들 수 있다.

    프로그램 분석, 생성 및 변환 기술의 다양한 가능한 사용법으로 인해, Java를 포함한 많은 언어에 대해 프로그램을 분석, 생성 및 변환하기 위한 많은 도구들이 구현되었다.

     

    ASM은 Java 언어를 위한 이러한 도구 중 하나로, 런타임 – 또는 오프라인 – 클래스 생성 및 변환을 위해 설계되었다.

    ASM 라이브러리는 컴파일된 Java 클래스에서 작동하도록 설계되었다. 가능한 한 빠르고 작게 설계되었다. 런타임에서 ASM을 사용하는 응용 프로그램의 속도를 너무 늦추지 않기 위해 가능한 한 빠르게 하는 것이 중요하다.

    메모리가 제한된 환경에서 사용되고, ASM을 사용하는 작은 애플리케이션 또는 라이브러리의 크기를 부풀리지 않기 위해 가능한 한 작게 하는 것도 중요하다. ASM은 컴파일된 Java 클래스를 생성하고 변환하기 위한 유일한 도구는 아니지만 가장 최근이자 효율적인 도구 중 하나이다. http://asm.objectweb.org에서 다운로드할 수 있으며, 주요 장점은 다음과 같다:

     

    • 사용하기 쉬운 단순하고 잘 설계된 모듈러 API를 가지고 있다.

    • 잘 문서화되어 있으며 관련된 Eclipse 플러그인을 제공한다.

    • 최신 Java 버전, Java 7을 지원한다.

    • 작고 빠르며 매우 견고하다.

    • 대규모 사용자 커뮤니티가 새로운 사용자에게 지원을 제공할 수 있다.

    • 오픈 소스 라이선스는 원하는 거의 모든 방식으로 사용할 수 있게 한다.

     

     

    1.2. 개요

    1.2.1. 범위(Scope)

    ASM 라이브러리의 목표는 디스크에 저장되고 Java 가상 머신에 로드되는 바이트 배열로 표현되는 컴파일된 Java 클래스를 생성, 변환 및 분석하는 것이다.

    이를 위해 ASM은 숫자 상수, 문자열, Java 식별자, Java 타입, Java 클래스 구조 요소 등 바이트보다 높은 수준의 개념을 사용하여 이러한 바이트 배열을 읽고, 쓰고, 변환하는 도구를 제공한다.

    ASM 라이브러리의 범위는 클래스의 읽기, 쓰기, 변환 및 분석에 엄격히 제한된다. 특히 클래스 로딩 프로세스는 범위에 포함되지 않는다.

     

    1.2.2. 모델(Model)

     

    ASM 라이브러리는 컴파일된 클래스를 생성하고 변환하기 위해 두 가지 API를 제공한다:

     

    1. 코어 API(Core API)는 클래스의 이벤트 기반(event based) 표현을 제공한다.

    2. 반면 트리 API(Tree API)는 객체 기반(object based) 표현을 제공한다.

     

    이벤트 기반 모델

    클래스는 이벤트 시퀀스로 표현되며, 각 이벤트는 클래스의 요소를 나타낸다.

    예를 들어 헤더, 필드, 메소드 선언, 명령 등이다.

    이벤트 기반 API는 가능한 이벤트 집합과 그것들이 발생해야 할 순서를 정의하며, 각 요소를 파싱하는 데 한 이벤트를 생성하는 클래스 파서와 이러한 이벤트 시퀀스에서 컴파일된 클래스를 생성하는 클래스 작성기를 제공한다.

     

    객체 기반 모델

    클래스는 객체의 트리로 표현되며, 각 객체는 클래스 자체, 필드, 메소드, 명령 등 클래스의 일부를 나타내고, 각 객체는 그 구성요소를 나타내는 객체에 대한 참조를 가진다.

    객체 기반 API는 클래스를 나타내는 이벤트 시퀀스를 동일한 클래스를 나타내는 객체 트리로 변환하는 방법을 제공하며, 그 반대로 객체 트리를 동등한 이벤트 시퀀스로 변환한다

    .

    즉, 객체 기반 API는 이벤트 기반 API 위에 구축된다.

     

    이 두 API는 XML 문서의 Simple API for XML(SAX) 및 Document Object Model(DOM) API와 비교될 수 있다.

    이벤트 기반 API는 SAX와 유사하며, 객체 기반 API는 DOM과 유사하다.

    객체 기반 API는 마치 DOM이 SAX 위에 제공될 수 있듯 이벤트 기반 API 위에 제공된다.

    ASM은 최고의 API가 없기 때문에 두 가지 API를 모두 제공한다. 실제로 각 API는 장단점이 있다:

     

    • 이벤트 기반 API는 객체 기반 API보다 빠르며 메모리를 덜 요구한다, 이는 클래스를 나타내는 객체 트리를 만들고 메모리에 저장할 필요가 없기 때문이다(이러한 차이는 SAX와 DOM 사이에도 존재한다).

    • 그러나 이벤트 기반 API를 사용하여 클래스 변환을 구현하는 것이 더 어려울 수 있다, 이는 한 번에 클래스의 한 요소만 사용할 수 있기 때문이다(현재 이벤트에 해당하는 요소), 객체 기반 API에서는 전체 클래스가 메모리에 있기 때문이다.

     

    두 API는 한 번에 하나의 클래스만 관리하며, 다른 클래스와 독립적이다:

    클래스 계층에 대한 정보가 유지되지 않으며, 클래스 변환이 다른 클래스에 영향을 미치는 경우 사용자가 이러한 다른 클래스를 수정해야 한다.

     

    1.2.3. 아키텍처

     

    ASM 애플리케이션은 강력한 아키텍처적 측면을 가지고 있다.

    실제로 이벤트 기반 API는 이벤트 생산자(클래스 파서), 이벤트 소비자(클래스 작성자) 및 다양한 사전 정의된 이벤트 필터를 중심으로 구성되며, 사용자 정의 생산자, 소비자 및 필터가 추가될 수 있다.

    • Event Producer : 클래스 파일을 읽고 파싱한다.
    • Event Consumer : 클래스 파일을 생성한다.
    • Event Filter : 클래스 파일에서 특정 요소들을 필터링한다.

     

    이 API를 사용하는 것은 따라서 두 단계 과정이다:

    • 이벤트 생산자, 필터 및 소비자 구성 요소를 가능하게 복잡한 아키텍처로 조립하고,

    • 그런 다음 이벤트 생산자(Counsumer)를 시작하여 생성 또는 변환 프로세스를 실행한다.

     

    객체 기반 API도 아키텍처적 측면을 가지고 있다: 실제로 객체 트리에서 작동하는 클래스 생성자 또는 변환기 구성 요소는 구성될 수 있으며, 그 사이의 링크는 변환 순서를 나타낸다.

     

    대부분의 ASM 애플리케이션에서 구성요소 아키텍처는 꽤 단순하지만, 클래스 파서, 작성자 또는 변환기 사이의 이벤트 기반 또는 객체 기반 통신을 나타내는 화살표가 있는 복잡한 아키텍처를 상상할 수 있다. 이는 이벤트 기반 및 객체 기반 표현 사이의 가능한 변환을 체인에서 어디에서나 포함할 수 있다.

     

     

     

     

    1.3. 구성

     

    ASM 라이브러리는 여러 jar 파일에 분포된 여러 패키지로 구성되어 있다:

     

    • org.objectweb.asm 및 org.objectweb.asm.signature 패키지

    이벤트 기반 API를 정의하고 클래스 파서 및 작성자 구성 요소를 제공한다. 이들은 asm.jar 아카이브에 포함되어 있다.

     

    • asm-util.jar 아카이브에 있는 org.objectweb.asm.util 패키지

    코어 API에 기반한 다양한 도구를 제공하며, ASM 애플리케이션의 개발 및 디버깅 중에 사용될 수 있다.

     

    • org.objectweb.asm.commons 패키지

    주로 코어 API를 기반으로 하는 몇 가지 유용한 사전 정의된 클래스 변환기를 제공한다. 이는 asm-commons.jar 아카이브에 포함되어 있다.

     

    • asm-tree.jar 아카이브의 org.objectweb.asm.tree 패키지

    객체 기반 API를 정의하고, 이벤트 기반 및 객체 기반 표현 간의 변환 도구를 제공한다.

     

    • org.objectweb.asm.tree.analysis 패키지

    클래스 분석 프레임워크와 여러 사전 정의된 클래스 분석기를 제공하며, 이는 트리 API를 기반으로 한다. 이는 asm-analysis.jar 아카이브에 포함되어 있다.

     

    이 문서는 두 부분으로 구성되어 있다.

    첫 번째 부분은 코어 API, 즉 asm, asm-util 및 asm-commons 아카이브를 다룬다.

    두 번째 부분은 트리 API, 즉 asm-tree 및 asm-analysis 아카이브를 다룬다. 각 부분은 클래스, 메소드 및 어노테이션, 제네릭 타입 등과 관련된 API를 위한 적어도 한 장을 포함한다.

     

    각 장은 프로그래밍 인터페이스뿐만 아니라 관련 도구 및 사전 정의된 구성 요소를 다룬다.

    모든 예제의 소스 코드는 ASM 웹 사이트에서 사용할 수 있다. 이 구성은 클래스 파일 기능을 점진적으로 소개하기 쉽게 만들지만, 때때로 하나의 ASM 클래스의 설명을 여러 섹션에 걸쳐 펼칠 필요가 있었다. 따라서 이 문서는 순차적으로 읽는 것이 권장된다. ASM API에 대한 참조 가이드는 Javadoc을 사용하라. 타이포그래픽 규칙 이탤릭체는 문장에서 요소를 강조하는 데 사용된다. 고정 폭 글꼴은 코드 조각에 사용된다. 볼드 고정 폭 글꼴은 코드 요소를 강조하는 데 사용된다. 이탤릭체 고정 폭 글꼴은 코드의 가변 부분과 레이블에 사용된다.

     

    1.4. 감사의 말

     

    이 문서의 작성 중 가치 있는 의견을 제공한 프랑수아 혼에게 감사를 표한다. 그의 의견은 이 문서의 구조와 가독성을 크게 향상시켰다.

     

     

     

    Reference

     

    https://asm.ow2.io/asm4-guide.pdf

     

    ASM USER GUIDE

     

    Copyright c 2007, 2011 Eric Bruneton All rights reserved. Redistribution and use in source (LYX format) and compiled forms (LATEX, PDF, PostScript, HTML, RTF, etc), with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code (LYX format) must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in compiled form (converted to LATEX, PDF, PostScript, HTML, RTF, and other formats) must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this documentation without specific prior written permission.

     

    THIS DOCUMENTATION IS PROVIDED BY THE AUTHOR “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

     

    Version 2.0, September 2011