바이트코드
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
바이트코드는 특정 하드웨어가 아닌 가상 머신에서 실행되도록 설계된 일종의 명령어 집합이다. 이는 이식성을 높여 다양한 플랫폼에서 실행될 수 있게 하지만, 인터프리터나 JIT 컴파일러를 거쳐야 하므로 실행 속도가 느려질 수 있다. 바이트코드는 스택 머신 또는 레지스터 머신 형태로 구현될 수 있으며, 자바, 파이썬, PHP 등 다양한 프로그래밍 언어와 가상 머신에서 활용된다. 최근에는 V8, 다트와 같은 일부 언어 구현에서 바이트코드 중개 없이 소스 코드에서 기계어로 직접 JIT 컴파일을 수행하는 방식을 시도하고 있다.
더 읽어볼만한 페이지
- 가상화 소프트웨어 - X86 가상화
X86 가상화는 x86 아키텍처 기반 시스템에서 가상 머신을 구현하는 기술로, 소프트웨어 기반 가상화와 하드웨어 지원 가상화로 나뉘며, CPU 제조사의 가상화 확장 기술을 활용하여 가상 머신의 성능을 향상시킨다. - 가상화 소프트웨어 - VM웨어 v스피어
VM웨어 v스피어는 VM웨어에서 개발한 서버 가상화 플랫폼으로, 다양한 운영체제 지원, 가상 시스템 확장, vMotion 개선, 스토리지 관리 효율성 향상 등의 특징을 가지며 클라우드 환경 지원 강화 및 관리 효율성 증대에 초점을 맞추어 지속적으로 업데이트되고 있다.
바이트코드 | |
---|---|
일반 정보 | |
다른 이름 | p-코드 (p-code) |
종류 | 중간 표현 |
설계 목적 | 소프트웨어 이식성 플랫폼 독립성 |
사용 예 | 파스칼 (UCSD 파스칼) 스몰토크 자바 (바이트코드) .NET 프레임워크 (CIL) 안드로이드 런타임 (Dalvik/ART) |
상세 정보 | |
정의 | 소프트웨어 인터프리터에 의해 실행되도록 설계된 명령어 집합의 형태 |
특징 | 플랫폼 독립적인 실행 가능 가상 머신 기반 실행 |
장점 | 이식성 향상 보안 강화 개발 속도 향상 |
단점 | 성능 저하 가능성 인터프리터 필요 |
역사 | 1960년대 후반, 소프트웨어 이식성을 위해 개발 |
기술적 측면 | |
스택 기반 아키텍처 | 일반적인 구현 방식 |
명령어 집합 | 간결하고 추상적인 명령어 사용 |
메모리 관리 | 인터프리터에 의해 관리됨 |
예시 | |
자바 바이트코드 | 자바 가상 머신 (JVM)에서 실행 |
.NET CIL | 공통 언어 런타임 (CLR)에서 실행 |
관련 기술 | |
가상 머신 | 바이트코드를 실행하는 환경 |
인터프리터 | 바이트코드를 해석하고 실행하는 프로그램 |
컴파일러 | 소스 코드를 바이트코드로 변환하는 프로그램 |
2. 역사
바이트코드는 소스 코드를 직접 해석하는 인터프리터의 이식성을 유지하면서 성능을 높이거나, 소스 코드 내용을 숨기기 위해 사용되는 중간 표현 방식이다. 이 중에서도 바이트코드는 인터프리터의 해석 실행 성능이 가장 높다는 장점을 가진다.
유닉스 보급 이후, 많은 컴퓨터가 바이트 단위 메모리 접근에 특화된 명령어를 제공하기 시작했다. 컴퓨터 메모리 접근은 해당 컴퓨터 고유의 크기인 워드 단위로 이루어질 때 가장 효율적이다. 또한, 실제 하드웨어의 기계어 성능을 높이기 위해, 기계어처럼 후속 주소를 순차적으로 읽는 메모리 접근 패턴은 많은 컴퓨터의 메모리 시스템에서 최적화되어 있다. 바이트코드는 이러한 컴퓨터에 가장 효율적인 메모리 단위와 접근 패턴에 맞춰 표현 체계를 구성한 것이다.
이러한 성능상의 이점 때문에, 오늘날 많은 인터프리터 언어들은 실제로 바이트코드로 컴파일된 후 바이트코드 인터프리터에 의해 실행된다. 자바 프로그램은 사용자 환경에 관계없이 성능을 확보할 수 있어, 소스 코드뿐만 아니라 바이트코드로 컴파일된 형태도 표준적으로 배포된다.
바이트코드는 실제 하드웨어의 기계어와 가장 유사한 중간 표현이므로, 기계어로 변환하기 직전의 중간 표현으로 사용되기도 한다. System/38은 소프트웨어 설치 시 바이트코드를 기계어로 변환하는 방식을 사용한 초기 컴퓨터 중 하나이다.
2. 1. 초기 역사
BCPL 프로그래밍 언어의 O-code는 초기 바이트코드 중 하나로, 1960년대에 BCPL 언어를 위해 설계되었다. 파스칼의 USCD 파스칼 구현체에서 사용된 p-code 역시 초기 바이트코드의 예시이다.1970년대에는 스몰토크 언어의 여러 구현체와 UCSD 파스칼에서 바이트코드가 활발하게 사용되었다. 1980년대에는 System/38과 같은 상용 시스템에서 바이트코드가 활용되었으며, System/38은 소프트웨어 설치 시 바이트코드를 기계어로 변환하는 방식을 사용했다.
2. 2. 발전 과정
1990년대에 자바 언어가 등장하면서 자바 가상 머신(JVM)에서 실행되는 자바 바이트코드가 널리 확산되었다. 자바 프로그램은 사용자 환경에 관계없이 성능을 확보할 수 있어 소스 코드뿐만 아니라 바이트 코드로 컴파일된 형태로도 배포되는 경우가 많다.[7]2000년대에는 .NET 프레임워크의 공통 중간 언어(CIL)와 안드로이드 플랫폼용으로 설계되어 달빅을 통해 실행되는 달빅 바이트코드 등 다양한 플랫폼에서 바이트코드가 활용되기 시작했다.[8]
이 외에도 다음과 같은 다양한 환경에서 바이트코드가 활용된다.
플랫폼 및 언어 | 설명 |
---|---|
액션스크립트 | 플래시 플레이어와 AIR의 일부인 액션스크립트 가상 머신(AVM)에서 실행되며, 컴파일러에 의해 바이트코드 포맷으로 변환된다. |
BANCStar | |
버클리 패킷 필터 | |
C to 자바 가상 머신 컴파일러 | |
커먼 리스프 | CLISP, CMUCL, Scieneer Common Lisp, 임베디드 커먼 리스프 구현체는 네이티브 코드나 바이트코드로 컴파일할 수 있다. |
공통 언어 런타임 | 공통 중간 언어 실행 |
디스 바이트코드(Dis bytecode) | |
에펠스튜디오 | |
EM(암스테르담 컴파일러 키트) 가상 머신 | |
이맥스 | |
얼랭 | 에릭슨 구현체는 BEAM 바이트코드를 사용한다. |
아이콘, 유니콘 | [7],[8] |
인포콤 | |
자바 바이트코드 | 자바 가상 머신에 의해 실행되며, ASM, 바이트 코드 엔지니어링 라이브러리, Javassist, JMangler 등이 있다. |
KEYB | 도스용 키보드 드라이버 |
LLVM | |
루아 | 레지스터 기반 바이트코드 가상 머신을 사용한다. |
MATLAB | m-코드[9] |
BCPL | O-code |
OCaml | 콤팩트 바이트코드 형태로 컴파일 가능 |
파스칼 | USCD 파스칼 구현체의 p-code |
패럿 가상 머신 | |
픽 베이직 | |
통계 컴퓨팅을 위한 R 환경 | |
스킴 | 스킴 48 구현체 |
스몰토크 | 수많은 구현체의 바이트코드 |
스핀 인터프리터 | |
SQLite | bespoke 바이트코드 포맷으로 SQL 문을 변환한다.[10] |
SWEET16 | |
Tcl | |
비주얼 폭스프로 | |
루비 | YARV 및 Rubinius |
2. 3. 최근 동향
유닉스 보급 이후, 많은 컴퓨터가 바이트 단위 메모리 접근에 특화된 명령어를 제공하게 되었다. 컴퓨터의 메모리 접근은 해당 컴퓨터 고유 크기인 워드 단위가 가장 효율적이다. 또한, 실제 하드웨어의 기계어 성능을 높이기 위해, 기계어와 마찬가지로 후속 주소를 순차적으로 읽는 메모리 접근 패턴은 많은 컴퓨터의 메모리 시스템에서 최적화되어 있다. 이러한 컴퓨터에 가장 효율적인 메모리 단위와 접근 패턴에 맞춰 표현 체계를 구성한 것이 바이트 코드이다. 이러한 성능상 이점 때문에, 현재 많은 인터프리터 언어는 실제로 바이트 코드로 컴파일된 후, 바이트 코드 인터프리터에 의해 실행된다.자바 프로그램은 사용자 환경에 관계없이 성능을 확보할 수 있어, 소스 코드뿐만 아니라 바이트 코드로 컴파일된 것도 표준적으로 배포되는 경우가 많다.
중간 표현 중에서도 실제 하드웨어 기계어와 가장 유사하므로, 기계어로 변환하기 직전의 중간 표현으로도 사용되는 경우가 있다. 바이트 코드를 사용한 초기 컴퓨터에는 System/38이 있으며, 소프트웨어 설치 시 기계어로 변환되었다.
3. 특징
바이트코드는 특정 가상 머신이나 인터프리터에 의해 실행되는 명령어 집합으로, 다음과 같은 특징을 갖는다.
- 이식성: 소스 코드를 직접 해석하는 것보다 효율적이며, 다양한 플랫폼에서 동일한 코드를 실행할 수 있게 해준다. 자바 코드는 바이트코드 형식으로 저장되어 JIT 컴파일을 통해 기계어로 번역되는데, 이는 소스 코드를 직접 해석하는 것보다 약 10배 빠르다.
- 실행 성능: 바이트코드 인터프리터는 이식성이 높고, 동적 번역기(JIT 컴파일러)는 런타임 시 바이트코드를 기계어로 번역한다. 많은 언어 구현에서 소스 코드를 바이트코드로 컴파일 후 가상 머신에 전달하는 방식을 사용한다. (자바, 라쿠, 파이썬, PHP 등). 유닉스 보급 이후, 많은 컴퓨터가 바이트 단위 메모리 접근에 특화된 명령어를 제공하며, 바이트코드는 이러한 환경에 맞춰 설계되어 성능이 높다.
- 보안: 소스 코드 내용을 숨기고 악의적인 코드 실행을 방지하는 데 도움이 된다.[10]
최근 V8과 다트는 바이트코드 없이 소스 코드에서 기계어로 직접 JIT 컴파일을 수행하여, 중간 바이트코드의 필요성에 대한 이의를 제기했다.
3. 1. 이식성
바이트코드는 소스 코드를 직접 해석하는 것보다 효율적이며, 다양한 플랫폼에서 동일한 코드를 실행할 수 있게 해준다. 예를 들어, 자바 및 스몰토크 코드는 일반적으로 바이트코드 형식으로 저장되며, 실행 전에 JIT 컴파일을 통해 기계어로 번역된다. 이 방식은 소스 코드를 직접 해석하는 것보다 실행 속도가 약 10배 정도 빠르다.오늘날 많은 언어 구현에서 소스 코드를 바이트코드로 컴파일한 후 가상 머신에 전달하는 두 단계 실행 방식을 사용한다. 이러한 바이트코드 기반 가상 머신은 자바, 라쿠, 파이썬, PHP, Tcl, mawk 및 Forth 등에서 사용된다.
유닉스가 보급된 이후, 많은 컴퓨터가 바이트 단위 메모리 접근에 특화된 명령어를 제공하게 되었다. 바이트코드는 이러한 컴퓨터의 효율적인 메모리 단위와 접근 패턴에 맞춰 설계되어 높은 성능을 제공한다. 이러한 성능상의 이점 때문에, 현재 많은 인터프리터 언어가 바이트코드로 컴파일된 후 바이트코드 인터프리터에 의해 실행된다.
자바 프로그램은 사용자의 환경에 관계없이 성능을 확보하기 위해 소스 코드뿐만 아니라 바이트코드로 컴파일된 형태로도 배포된다.
3. 2. 실행 성능
바이트코드 프로그램은 명령어를 한 번에 하나씩 구문 분석하고 ''직접'' 실행할 수 있는데, 이러한 종류의 ''바이트코드 인터프리터''는 이식성이 매우 높다. 동적 번역기 또는 JIT 컴파일러라고 하는 일부 시스템은 런타임 시 필요에 따라 바이트코드를 기계어로 번역한다. 이렇게 하면 가상 머신이 하드웨어에 종속되지만, 바이트코드의 이식성은 유지된다. 예를 들어, 자바 및 스몰토크 코드는 일반적으로 바이트코드 형식으로 저장되며, 일반적으로 실행 전에 JIT 컴파일되어 기계어로 번역된다. 이는 소스 코드를 직접 해석하는 것보다 실행 속도가 상당히 향상되며, 일반적으로 약 10배 정도 빨라진다.성능상의 이점 때문에 오늘날 많은 언어 구현은 먼저 소스 코드를 바이트코드로 컴파일한 다음, 바이트코드를 가상 머신에 전달하는 두 단계로 프로그램을 실행한다. 이러한 종류의 바이트코드 기반 가상 머신은 자바, 라쿠, 파이썬, PHP, Tcl, mawk 및 Forth에서 사용된다(그러나 Forth는 이러한 방식으로 바이트코드를 통해 컴파일되는 경우가 거의 없으며, 해당 가상 머신은 더 일반적이다). 펄 및 루비 1.8의 구현은 대신 소스 코드에서 파생된 추상 구문 트리 표현을 통해 작동한다.
최근에는 V8 및 다트의 개발자들이 중간 바이트코드가 빠르고 효율적인 VM 구현에 필요하다는 개념에 이의를 제기했다. 이 두 언어 구현 모두 현재 바이트코드 중개 없이 소스 코드에서 기계어로 직접 JIT 컴파일을 수행한다.
소스 코드를 직접 해석하는 인터프리터와 동등한 이식성을 확보하면서 인터프리터의 성능을 높이거나, 소스 코드의 내용을 숨기는 것이 목적이라면, 어떠한 중간 표현으로도 충분하다. 이러한 중간 표현 중에서 바이트 코드의 의의는 얻을 수 있는 인터프리터의 해석 실행 성능이 가장 높다는 것이다.
유닉스가 보급된 이래로, 많은 컴퓨터에는 바이트 단위의 메모리 액세스에 특화된 명령이 제공되고 있다. 또는, 컴퓨터의 메모리 액세스는 해당 컴퓨터 고유의 크기인 워드 단위가 가장 효율적이다. 더욱이, 실제 하드웨어의 기계어의 성능을 높이기 위해, 기계어와 마찬가지로 후속 주소를 순차적으로 읽어 들이는 메모리 액세스 패턴은, 많은 컴퓨터의 메모리 시스템에서 최적화되어 있다. 컴퓨터에게 가장 효율적인 메모리 단위와 액세스 패턴에, 표현 체계를 맞춘 것이 바이트 코드이다. 이러한 성능상의 이점으로 인해, 현재 많은 인터프리터 언어는 실제로는 바이트 코드로 컴파일된 후, 바이트 코드 인터프리터에 의해 실행된다.
자바 프로그램은, 사용자의 환경에 관계없이 성능을 확보할 수 있기 때문에, 소스 코드뿐만 아니라 바이트 코드로 컴파일된 것도 표준적으로 배포되는 경우가 많다.
또한, 중간 표현 중에서도 실제 하드웨어의 기계어와 가장 유사한 것이므로, 기계어로 변환하기 직전의 중간 표현으로도 사용되는 경우가 있다. 바이트 코드를 사용한 초기 컴퓨터에는 System/38이 있으며, 소프트웨어 설치 시 기계어로 변환되었다.
3. 3. 보안
바이트코드는 소스 코드의 내용을 숨기고, 악의적인 코드 실행을 방지하는 데 도움이 된다.[10] 예를 들어, 자바 프로그램은 사용자의 환경에 관계없이 성능을 확보할 수 있기 때문에 소스 코드뿐만 아니라 바이트코드로 컴파일된 것도 표준적으로 배포되는 경우가 많다. SQLite 데이터베이스 엔진은 SQL 문을 bespoke 바이트코드 포맷으로 변환한다.[10]3. 4. 스택 머신 vs 레지스터 머신
바이트코드는 스택 머신 또는 레지스터 머신 형태로 구현될 수 있으며, 각각 장단점이 존재한다. 추상 기계라고 불리는 계산 모델로서의 성격이 강한 기계의 경우, 이론적인 처리를 위해 스택이 사용되는 경우도 있다.[6]- 스택 머신 (Stack Machine)
- 명령 집합에서 암묵적으로 스택 탑을 오퍼랜드로 사용하며, 오퍼랜드 위치를 명시하는 영역이 불필요하다.[6]
- 목적하는 오퍼랜드가 스택 탑에 없는 경우에는 오퍼랜드 이동을 위한 명령을 추가한다.[6]
- 스택 머신 명령 한 개당 길이와 기능은 레지스터 머신 한 명령 내의 개별 오퍼랜드 필드 한 개 또는 코드 필드와 동등하다.[6]
- 명령 순서를 재정렬하여 오퍼랜드 이동 명령을 생략할 수 있다.[6]
- 오퍼랜드 이동을 생략하면 스택 머신이 동등한 프로그램을 더 짧게 기술할 수 있는 경우가 많다. 데이터 캐시 적중률도 높아져 프로그램 크기 감소가 실질적인 속도 개선으로 이어진다.[6]
- 오퍼랜드 이동을 생략해도 스택 머신이 레지스터 머신보다 명령 수가 많아진다.[6]
- 스택 머신형 인터프리터에서는 대부분 명령의 피연산자가 스택 탑으로 정해져 있고, 참조할 물리 레지스터를 컴파일 시 결정할 수 있으므로, 스택 탑 몇 개를 물리 레지스터로 구현한다.[6]
- 많은 실제 기기에서 레지스터를 통한 데이터 전달은 1클럭으로 가능하지만, 메모리를 통한 데이터 전달은 수 클럭을 필요로 하므로, 바로 앞 명령의 결과를 바로 뒤 명령이 사용하는 처리가 이어진 경우 레지스터 머신은 불리하다.[6]
- ALGOL 이후 많은 프로그래밍 언어는 문맥 자유 문법으로 기술할 수 있으며, 스택 머신과 유사한 푸시다운 오토마타로 구문 분석할 수 있다. 따라서 스택 머신용 코드 생성기는 구문 분석기와 일체화하여 메모리 절약 및 고속화가 가능하다.[6]
- 자바 가상 머신 등 스택 머신도 많다.[6]
- 레지스터 머신 (Register Machine)
- 명령 집합에서 오퍼랜드 위치를 명령 내에서 명시한다.[6]
- 개별 명령이 매우 단순한 처리만 수행하는 바이트코드 인터프리터에서는 명령 종류를 판정하고 분기하는 처리가 실행 시간의 큰 부분을 차지하므로, 이 점에서 레지스터 머신이 유리하다.[6]
- 레지스터 머신형 인터프리터에서는 번호로 가상 레지스터를 지정하지만, 많은 실제 기기에서는 실행 시 물리 레지스터를 번호로 참조할 수 없기 때문에 메모리 배열로 가상 레지스터를 구현하는 경우가 많다.[6]
- 레지스터 머신은 한정된 레지스터를 재사용하는 레지스터 할당을 수행해야 한다. 단, 인터프리터의 가상 레지스터는 메모리 배열로 구현되는 경우가 많다.[6]
- Lua 버전 5나 달빅 가상 머신 등 레지스터 머신도 많다.[6]
4. 작동 방식
소스 코드를 직접 해석하는 인터프리터와 동등한 이식성을 확보하면서 인터프리터의 성능을 높이거나, 소스 코드의 내용을 숨기는 것이 목적이라면 어떠한 중간 표현으로도 충분하다. 이러한 중간 표현 중에서 바이트코드의 의의는 인터프리터의 해석 실행 성능이 가장 높다는 것이다.
유닉스가 보급된 이래로, 많은 컴퓨터에는 바이트 단위의 메모리 접근에 특화된 명령이 제공되고 있다. 컴퓨터의 메모리 접근은 해당 컴퓨터 고유의 크기인 워드 단위가 가장 효율적이다. 또한, 실제 하드웨어의 기계어 성능을 높이기 위해 기계어와 마찬가지로 후속 주소를 순차적으로 읽어 들이는 메모리 접근 패턴은 많은 컴퓨터의 메모리 시스템에서 최적화되어 있다. 바이트코드는 이러한 컴퓨터에게 가장 효율적인 메모리 단위와 접근 패턴에 표현 체계를 맞춘 것이다. 이러한 성능상의 이점으로 인해 현재 많은 인터프리터 언어는 실제로 바이트코드로 컴파일된 후, 바이트코드 인터프리터에 의해 실행된다.
자바 프로그램은 사용자의 환경에 관계없이 성능을 확보할 수 있기 때문에 소스 코드뿐만 아니라 바이트코드로 컴파일된 것도 표준적으로 배포되는 경우가 많다.
또한, 중간 표현 중에서도 실제 하드웨어의 기계어와 가장 유사한 것이므로, 기계어로 변환하기 직전의 중간 표현으로도 사용되는 경우가 있다. 바이트코드를 사용한 초기 컴퓨터에는 System/38이 있으며, 소프트웨어 설치 시 기계어로 변환되었다.
4. 1. 인터프리터 방식
바이트코드 인터프리터는 바이트코드를 한 줄씩 읽어 해석하고 실행한다. 이러한 방식은 이식성이 높지만, 실행 속도는 상대적으로 느리다.성능상의 이점 때문에 오늘날 많은 언어 구현은 소스 코드를 먼저 바이트코드로 컴파일한 다음, 바이트코드를 가상 머신에 전달하는 두 단계로 프로그램을 실행한다. 이러한 방식의 바이트코드 기반 가상 머신은 자바, 라쿠, 파이썬, PHP, Tcl, mawk 및 Forth에서 사용된다. 그러나 펄 및 루비 1.8은 소스 코드에서 파생된 추상 구문 트리 표현을 통해 작동한다.
최근에는 V8 및 다트 개발자들이 중간 바이트코드가 빠르고 효율적인 VM 구현에 필수적이라는 개념에 이의를 제기하기도 했다. 이들은 바이트코드 중개 없이 소스 코드에서 기계어로 직접 JIT 컴파일을 수행한다.
소스 코드를 직접 해석하는 인터프리터와 동등한 이식성을 확보하면서 인터프리터의 성능을 높이거나, 소스 코드의 내용을 숨기는 것이 목적이라면 어떠한 중간 표현으로도 충분하다. 이러한 중간 표현 중에서 바이트코드의 의의는 얻을 수 있는 인터프리터의 해석 실행 성능이 가장 높다는 것이다.
유닉스가 보급된 이래로, 많은 컴퓨터에는 바이트 단위의 메모리 접근에 특화된 명령이 제공되고 있다. 컴퓨터의 메모리 접근은 해당 컴퓨터 고유의 크기인 워드 단위가 가장 효율적이다. 또한, 실제 하드웨어의 기계어 성능을 높이기 위해 기계어와 마찬가지로 후속 주소를 순차적으로 읽어 들이는 메모리 접근 패턴은 많은 컴퓨터의 메모리 시스템에서 최적화되어 있다. 바이트코드는 이러한 컴퓨터에게 가장 효율적인 메모리 단위와 접근 패턴에 표현 체계를 맞춘 것이다. 이러한 성능상의 이점으로 인해 현재 많은 인터프리터 언어는 실제로 바이트코드로 컴파일된 후, 바이트코드 인터프리터에 의해 실행된다.
자바 프로그램은 사용자의 환경에 관계없이 성능을 확보할 수 있기 때문에 소스 코드뿐만 아니라 바이트코드로 컴파일된 것도 표준적으로 배포되는 경우가 많다.
또한, 중간 표현 중에서도 실제 하드웨어의 기계어와 가장 유사한 것이므로, 기계어로 변환하기 직전의 중간 표현으로도 사용되는 경우가 있다.
4. 2. JIT(Just-In-Time) 컴파일 방식
JIT(Just-In-Time) 컴파일러는 런타임 시 필요에 따라 바이트코드를 기계어로 번역한다. 이렇게 하면 가상 머신이 하드웨어에 종속되지만 바이트코드의 이식성은 유지된다. 예를 들어, 자바 및 스몰토크 코드는 일반적으로 바이트코드 형식으로 저장되며, 실행 전에 JIT 컴파일을 통해 기계어로 번역된다. 이 방식은 프로그램 실행 전 지연이 발생하지만, 소스 코드를 직접 해석하는 것보다 실행 속도가 약 10배 정도 향상된다.성능상의 이점 때문에 오늘날 많은 언어 구현은 소스 코드를 바이트코드로 컴파일한 다음, 바이트코드를 가상 머신에 전달하는 두 단계로 프로그램을 실행한다. 이러한 바이트코드 기반 가상 머신은 자바, 라쿠, 파이썬, PHP, Tcl, mawk 및 Forth에서 사용된다.
최근에는 V8 및 다트 개발자들이 중간 바이트코드가 빠르고 효율적인 VM 구현에 필요하다는 개념에 이의를 제기했다. 이 두 언어 구현은 현재 바이트코드 중개 없이 소스 코드에서 기계어로 직접 JIT 컴파일을 수행한다.
5. 한국에서의 활용 사례
(바이트코드 문서의 "한국에서의 활용 사례" 섹션은 원본 소스에 관련 내용이 없으므로 작성할 수 없습니다.)
6. 다양한 바이트코드의 예
다음은 다양한 프로그래밍 언어 및 플랫폼에서 사용되는 바이트코드의 예시이다.
- 액션스크립트: 플래시 플레이어와 AIR의 일부인 액션스크립트 가상 머신(AVM)에서 실행된다. 액션스크립트 코드는 일반적으로 컴파일러에 의해 바이트코드 포맷으로 변환된다.
- 어도비 플래시 오브젝트
- BANCStar
- 버클리 패킷 필터
- 바이트 코드 엔지니어링 라이브러리
- C to 자바 가상 머신 컴파일러
- 커먼 리스프
- CLISP 구현체
- CMUCL 및 Scieneer Common Lisp 구현체: 네이티브 코드나 바이트코드로 컴파일할 수 있다.
- 임베디드 커먼 리스프 구현체: 바이트코드나 C 코드로 컴파일이 가능하다.
- 공통 중간 언어: 공통 언어 런타임에 의해 실행된다.
- 달빅 바이트코드: 안드로이드 플랫폼용으로 설계되어 달빅을 통해 실행된다.
- 디스 바이트코드(Dis bytecode)
- 에펠스튜디오
- EM(암스테르담 컴파일러 키트) 가상 머신
- 이맥스
- 얼랭의 에릭슨 구현체: BEAM 바이트코드를 사용한다.
- 아이콘[7]과 유니콘[8]
- 인포콤
- 자바 바이트코드: 자바 가상 머신에 의해 실행.
- KEYB: 도스용 키보드 드라이버
- LLVM
- 루아 언어: 레지스터 기반 바이트코드 가상 머신을 사용한다.
- MATLAB 언어의 m-코드[9]
- BCPL 프로그래밍 언어의 O-code
- OCaml 언어: 선택적으로 콤팩트 바이트코드 형태로 컴파일한다.
- 파스칼의 USCD 파스칼 구현체의 p-code
- 패럿 가상 머신
- 픽 베이직
- 통계 컴퓨팅을 위한 R 환경
- 스킴의 스킴 48 구현체
- 스몰토크 언어의 수많은 구현체의 바이트코드.
- 스핀 인터프리터
- SQLite 데이터베이스 엔진: SQL 문을 bespoke 바이트코드 포맷으로 변환한다.[10]
- SWEET16
- Tcl
- 비주얼 폭스프로
- 루비용 YARV 및 Rubinius
6. 1. 프로그래밍 언어
자바 프로그램은 사용자의 환경에 관계없이 성능을 확보할 수 있기 때문에 소스 코드뿐만 아니라 바이트코드로 컴파일된 것도 표준적으로 배포되는 경우가 많다.[10] JVM에서 실행되는 자바 바이트코드는 다음과 같다.이름 |
---|
ASM |
BCEL |
Javassist |
- C#과 같은 .NET 언어에서 사용되는 공통 중간 언어(CIL)는 공통 언어 런타임에 의해 실행된다.
- 파이썬 스크립트는 실행 시 파이썬의 바이트코드 언어로 컴파일되고, 컴파일된 파일(.pyc)은 스크립트 폴더 내에 캐시된다.
- 루아 언어는 레지스터 기반 바이트코드 가상 머신을 사용한다.
- 얼랭의 에릭슨 구현체는 BEAM 바이트코드를 사용한다.
- 스몰토크 언어의 수많은 구현체는 바이트코드를 사용한다.
6. 2. 가상 머신
자바 가상 머신(JVM)은 자바 바이트코드를 실행하는 가상 머신이다.[7] ASM, 바이트 코드 엔지니어링 라이브러리, Javassist 등이 JVM에서 사용된다.공통 언어 런타임(CLR)은 공통 중간 언어를 실행하는 가상 머신으로, C#과 같은 .NET 언어에서 사용된다.
달빅 가상 머신(Dalvik VM)은 안드로이드 플랫폼용으로 설계된 달빅 바이트코드를 실행한다.[8] ART (Android Runtime)는 안드로이드 런타임으로, 달빅 가상 머신을 대체한다.
패럿 가상 머신은 동적 프로그래밍 언어를 위해 설계된 가상 머신이다.
SQLite 데이터베이스 엔진은 SQL 문을 bespoke 바이트코드 포맷으로 변환하여 실행한다.[10]
웹어셈블리는 웹 브라우저에서 실행되는 이식 가능한 바이너리 코드 형식이다.
7. 비판 및 한계
바이트코드는 특정 가상 머신에 종속적이어서 해당 가상 머신이 없는 환경에서는 실행할 수 없다는 단점이 있다. 또한, JVM에서 실행되는 자바 바이트코드와 같이, JIT 컴파일 방식을 사용하는 경우 초기 실행 시 오버헤드가 발생할 수 있다.
8. 결론
바이트코드는 소프트웨어 개발에서 이식성, 실행 성능, 보안 등 다양한 측면에서 중요한 역할을 수행하고 있다. 소스 코드를 직접 해석하는 인터프리터와 동등한 이식성을 확보하면서 인터프리터의 성능을 높이거나, 소스 코드의 내용을 숨기는 것이 목적이라면 중간 표현으로도 충분하다. 이러한 중간 표현 중에서 바이트 코드는 인터프리터의 해석 실행 성능이 가장 높다는 장점이 있다.[1]
유닉스 보급 이후, 많은 컴퓨터에는 바이트 단위 메모리 접근에 특화된 명령이 제공되고 있다. 바이트 코드는 컴퓨터에 가장 효율적인 메모리 단위와 접근 패턴에 맞춰진 표현 체계이다. 이러한 성능상 이점 때문에, 현재 많은 인터프리터 언어는 실제로는 바이트 코드로 컴파일된 후, 바이트 코드 인터프리터에 의해 실행된다.[1]
자바 프로그램은 사용자 환경에 관계없이 성능을 확보할 수 있어, 소스 코드뿐만 아니라 바이트 코드로 컴파일된 것도 표준적으로 배포되는 경우가 많다. 또한, 중간 표현 중에서도 실제 하드웨어의 기계어와 가장 유사하므로, 기계어로 변환하기 직전의 중간 표현으로도 사용된다. 바이트 코드를 사용한 초기 컴퓨터에는 System/38이 있으며, 소프트웨어 설치 시 기계어로 변환되었다.[1]
한국에서도 자바, 안드로이드 앱 개발 등 다양한 분야에서 널리 활용되고 있으며, 앞으로도 웹어셈블리 등 새로운 기술 발전에 따라 더욱 중요한 역할을 할 것으로 예상된다.
참조
[1]
웹사이트
Exploring the New PHP JIT Compiler
https://www.zend.com[...]
2021-02-19
[2]
웹사이트
PHP 8: The JIT - stitcher.io
https://stitcher.io/[...]
2021-02-19
[3]
웹사이트
Berkeley Pascal
https://github.com/a[...]
2022-07-11
[4]
웹사이트
CLHS: Function DISASSEMBLE
http://www.lispworks[...]
[5]
웹사이트
The Common Lisp Cookbook – Performance Tuning and Tips
https://lispcookbook[...]
2023-12-13
[6]
문서
実機ではデコーダやエンコーダといった論理回路に向いたビットパターンのほうが好まれるといった細かい傾向の違いなどはある。
[7]
웹인용
The Implementation of the Icon Programming Language
http://www.cs.arizon[...]
2017-04-01
[8]
문서
The Implementation of Icon and Unicon a Compendium
http://unicon.source[...]
[9]
웹인용
United States Patent 6,973,644
http://patft.uspto.g[...]
2017-04-01
[10]
웹인용
The SQLite Bytecode Engine
https://www.sqlite.o[...]
2017-04-01
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com