가상 머신이란 무엇인가요?
가상 머신이란 무엇입니까?
가상 머신의 개념은 비교적 광범위합니다. 사람들이 일반적으로 접하는 가상 머신 개념에는 VMware와 같은 하드웨어 시뮬레이션 소프트웨어, 하드웨어와 컴파일러 사이에 있는 JVM과 같은 소프트웨어가 포함됩니다. 여기서 언급하는 것은 후자이다.
가상 머신은 실제 컴퓨터처럼 명령어 세트가 있고 다양한 저장 영역을 사용하는 추상적인 컴퓨터입니다. 명령을 실행하고 데이터, 메모리 및 레지스터를 관리하는 역할을 담당합니다. 이 가상 머신은 모든 플랫폼의 컴파일러에 일관된 인터페이스를 제공합니다. 컴파일러는 가상 머신을 지향하고 가상 머신이 이해할 수 있는 코드를 생성하기만 하면 통역사가 가상 머신 코드를 특정 시스템의 실행을 위한 머신 코드로 변환합니다.
자바 가상 머신
1. 자바 가상 머신이란
자바 가상 머신은 실제 컴퓨터에서 소프트웨어를 통해 시뮬레이션되는 가상의 머신입니다. . Java 가상 머신에는 프로세서, 스택, 레지스터 등과 같은 자체 가상 하드웨어가 있으며 해당 명령어 시스템도 있습니다.
1. 자바 가상 머신을 사용하는 이유
자바 언어의 가장 중요한 특징은 플랫폼으로부터의 독립성입니다. 이 기능을 달성하려면 Java 가상 머신을 사용하는 것이 핵심입니다. 일반적인 고급 언어를 다른 플랫폼에서 실행하려면 최소한 다른 대상 코드로 컴파일해야 합니다. Java 언어 가상 머신이 도입된 이후에는 다른 플랫폼에서 실행될 때 Java 언어를 다시 컴파일할 필요가 없습니다. Java 언어 사용 모델 Java 가상 머신은 특정 플랫폼과 관련된 정보를 보호하므로 Java 언어 컴파일러는 Java 가상 머신에서 실행되는 대상 코드(바이트코드)만 생성하면 되며 수정 없이 여러 플랫폼에서 실행할 수 있습니다. JVM(Java Virtual Machine)이 바이트코드를 실행할 때 바이트코드를 특정 플랫폼에서 실행하기 위한 기계 명령어로 해석합니다.
2. Java Virtual Machine을 이해해야 하는 사람
Java Virtual Machine은 Java 언어의 기본 구현을 위한 기초입니다. 자바 가상 머신에 대한 이해. 이는 Java 언어의 일부 속성을 이해하는 데 도움이 되며 Java 언어를 사용하는 데도 도움이 됩니다. 특정 플랫폼에서 Java 가상 머신을 구현하려는 소프트웨어 담당자, Java 언어의 컴파일러 작성자, 하드웨어 칩을 사용하여 Java 가상 머신을 구현하려는 사람들은 Java 가상 머신의 사양에 대한 깊은 이해가 있어야 합니다. 가상 머신. 또한, 자바 언어를 확장하거나 다른 언어를 자바 언어 바이트코드로 컴파일하려면 자바 가상 머신에 대한 깊은 이해도 필요하다.
3. 자바 가상 머신이 지원하는 데이터 타입
자바 언어로 자바 가상 머신이 지원하는 기본 데이터 타입은 다음과 같다.
byte ://1바이트는 부호 있는 정수의 보수
short://2바이트 부호 있는 정수의 보수
int://4바이트의 보수 부호 있는 정수
long://8바이트 부호 있는 정수의 보수
float://4바이트 IEEE754 단정밀도 부동 소수점 숫자
double: //8바이트 IEEE754 배정밀도 부동 소수점 숫자
char://2바이트 부호 없는 유니코드 문자
거의 모든 Java 유형 검사는 컴파일 타임에 수행됩니다. 위에 나열된 기본 데이터 유형의 데이터는 Java로 실행될 때 하드웨어 태그를 지정할 필요가 없습니다. 이러한 원시 데이터형 데이터 자체를 연산하는 바이트코드(명령어)는 피연산자의 데이터형을 가리킨다. 예를 들어 iadd, ladd, fadd, dadd 명령어는 모두 두 개의 숫자를 더하고 그 피연산자 유형은 int, long, 플로트 및 더블. 가상 머신은 불리언(Boolean) 타입에 대해 별도의 명령을 설정하지 않습니다. 부울 데이터는 정수 반환을 포함하여 정수 명령어로 처리됩니다. 부울 배열은 바이트 배열을 사용하여 처리됩니다. 가상 머신은 IEEE754 형식의 부동 소수점 숫자를 사용합니다. IEEE 형식을 지원하지 않는 구형 컴퓨터에서는 Java 수치 계산 프로그램을 실행할 때 속도가 매우 느려질 수 있습니다.
가상 머신이 지원하는 기타 데이터 유형은 다음과 같습니다:
object//Javaobject(객체)에 대한 4바이트 참조
returnAddress//4바이트 , jsr/ret/jsr-w/ret-w 명령에 사용됨
참고: Java 배열은 객체로 처리됩니다.
가상 머신의 사양에는 개체의 내부 구조에 대한 특별한 요구 사항이 없습니다. Sun 구현에서 객체에 대한 참조는 포인터 쌍을 포함하는 핸들입니다. 한 포인터는 객체의 메소드 테이블을 가리키고 다른 포인터는 객체의 데이터를 가리킵니다. JVM(Java Virtual Machine) 바이트코드로 표현되는 프로그램은 유형 규칙을 준수해야 합니다. JVM(Java Virtual Machine) 구현은 유형 사양을 위반하는 바이트코드 프로그램 실행을 거부해야 합니다. JVM(Java Virtual Machine)은 바이트코드 정의의 제한으로 인해 32비트 주소 공간이 있는 시스템에서만 실행될 수 있는 것으로 보입니다. 그러나 바이트코드를 64비트 형식으로 자동 변환하는 Java 가상 머신을 생성할 수 있습니다. Java 가상 머신이 지원하는 데이터 유형을 보면 Java는 데이터 유형의 내부 형식에 대해 엄격한 규정을 두고 있으므로 다양한 Java 가상 머신의 구현이 데이터를 동일한 방식으로 해석하여 플랫폼 독립성을 보장한다는 것을 알 수 있습니다. 자바와 이식성
.
2. Java 가상 머신 아키텍처
Java 가상 머신은 명령어 세트, 레지스터 세트, 스택 및 가비지 수집 힙의 다섯 부분으로 구성됩니다. 수집된 힙), 메소드 영역입니다. 이 5개 부분은 자바 가상 머신의 논리적 구성 요소로 어떤 구현 기술이나 구성 방법에 의존하지 않지만, 이들의 기능은 실제 머신에서 어떤 방식으로든 구현되어야 합니다.
1.Java 명령어 세트
Java Virtual Machine은 대략 248바이트 코드를 지원합니다. 각 바이트코드는 레지스터에 정수 추가, 서브루틴 전송 등과 같은 기본 CPU 작업을 수행합니다. Java 명령어 세트는 Java 프로그램의 어셈블리 언어와 동일합니다.
Java 명령 세트의 명령에는 수행할 작업을 지정하는 단일 바이트 연산자와 작업에 필요한 매개변수 또는 데이터를 제공하는 0개 이상의 피연산자가 포함되어 있습니다. 많은 명령어에는 피연산자가 없고 단일 바이트 연산자로만 구성됩니다.
가상 머신의 내부 루프 실행 과정은 다음과 같습니다.
do{
연산자 바이트를 가져옵니다. 작업에 따라 기호의 값을 기반으로 작업을 실행합니다.
}동안(프로그램이 끝나지 않음)
명령 시스템의 단순성으로 인해 가상 머신은 실행 프로세스가 매우 간단하여 실행 효율성을 높이는 데 도움이 됩니다. 명령어의 피연산자의 수와 크기는 연산자에 의해 결정됩니다. 피연산자가 1바이트보다 크면 상위 바이트부터 먼저 저장됩니다. 예를 들어, 16비트 매개변수는 저장 시 2바이트를 차지하며 해당 값은 다음과 같습니다.
첫 번째 바이트 * 256 + 두 번째 바이트는 일반적으로 바이트만 정렬됩니다. 내부적으로 필수 4바이트 경계 정렬이 필요한 tabltch 및 조회 명령은 예외입니다.
2. 레지스터
Java Virtual Machine의 레지스터는 마이크로프로세서의 일부 특수 레지스터와 유사하게 시스템의 실행 상태를 저장하는 데 사용됩니다.
Java Virtual Machine에는 네 가지 유형의 레지스터가 있습니다.
pc: Java 프로그램 카운터.
optop: 피연산자 스택의 맨 위에 대한 포인터입니다.
프레임: 현재 실행 메서드의 실행 환경에 대한 포인터입니다.
vars: 현재 실행 중인 메서드의 지역 변수 영역에 있는 첫 번째 변수를 가리키는 포인터입니다.
Java Virtual Machine
Java Virtual Machine은 매개변수를 전달하거나 수신하기 위해 레지스터를 정의하거나 사용하지 않습니다. 그 목적은 명령어 세트의 단순성을 보장하는 것입니다. 및 구현 시간(특히 레지스터 수가 적은 프로세서의 경우)
모든 레지스터는 32비트입니다.
3. 스택
Java Virtual Machine의 스택은 로컬 변수 영역, 실행 환경 영역, 피연산자 영역의 세 가지 영역으로 구성됩니다.
(1) 지역 변수 영역 각 Java 메소드는 고정 크기의 지역 변수 세트를 사용합니다. vars 레지스터의 워드 오프셋에서 주소가 지정됩니다. 지역 변수는 모두 32비트입니다. 긴 정수와 배정밀도 부동 소수점 숫자는 두 지역 변수의 공간을 차지하지만 첫 번째 지역 변수의 인덱스에 따라 주소가 지정됩니다. (예를 들어 인덱스 n을 갖는 지역변수가 배정밀도 부동소수점 숫자라면 실제로는 인덱스 n과 n+1로 표현되는 저장공간을 차지한다.) 가상머신 사양에서는 지역변수에 64비트를 요구하지 않는다. 값은 64비트로 정렬됩니다. 가상 머신은 로컬 변수의 값을 피연산자 스택에 로드하는 명령을 제공하고, 피연산자 스택의 값을 로컬 변수에 쓰는 명령도 제공합니다.
(2) 실행 환경 영역 실행 환경에 포함된 정보는 동적 연결, 일반 메소드 반환 및 예외 전파에 사용됩니다.
·동적 연결
실행 환경에는 현재 클래스와 현재 메서드의 인터프리터 기호 테이블에 대한 포인터가 포함되어 있으며, 이는 메서드 코드의 동적 연결을 지원하는 데 사용됩니다. 메서드의 클래스 파일 코드는 호출할 메서드와 액세스할 변수를 참조할 때 기호를 사용합니다. 동적 연결은 기호 메서드 호출을 실제 메서드 호출로 변환하고, 아직 정의되지 않은 기호를 해석하는 데 필요한 클래스를 로드하며, 변수 액세스를 해당 변수의 런타임 저장 구조에 해당하는 오프셋 주소로 변환합니다. 메소드와 변수를 동적으로 연결하면 메소드에 사용된 다른 클래스의 변경사항이 이 프로그램의 코드에 영향을 주지 않습니다.
·일반 메서드 반환
현재 메서드가 정상적으로 종료되면 올바른 유형의 반환 명령이 실행될 때 호출된 메서드가 반환 값을 가져옵니다. 실행 환경은 정상적으로 반환될 때 호출자의 레지스터를 복원하는 데 사용되며 실행된 메서드 호출 명령을 건너뛰기 위해 호출자의 프로그램 카운터를 적절한 값만큼 증가시킨 다음 호출자의 실행 환경에서 실행을 계속합니다.
·예외 및 오류 전파
Java에서는 예외를 Error 또는 Exception이라고 합니다. 프로그램에서의 원인은 다음과 같습니다. 필요한 클래스 파일을 찾을 수 없습니다. ②널 포인터 참조 등 런타임 오류
·프로그램이 throw 문을 사용합니다.
예외가 발생하면 Java Virtual Machine은 다음과 같은 조치를 취합니다.
·현재 메서드와 관련된 catch 절 테이블을 확인합니다. 각 catch 절에는 유효한 명령어 범위, 처리할 수 있는 예외 유형, 예외를 처리하는 코드 블록의 주소가 포함됩니다.
·예외와 일치하는 catch 절은 다음 조건을 충족해야 합니다. 예외를 발생시킨 명령이 해당 명령 범위 내에 있고 발생한 예외 유형이 처리할 수 있는 예외 유형의 하위 유형입니다. . 일치하는 catch 절이 발견되면 시스템은 지정된 예외 처리 블록으로 실행을 전송합니다. 예외 처리 블록이 없으면 현재 메서드의 모든 중첩된 catch 절이 검사될 때까지 일치하는 catch 절을 찾는 프로세스가 반복됩니다.
가상 머신은 일치하는 첫 번째 catch 절부터 실행을 계속하므로 catch 절 테이블의 순서가 중요합니다. Java 코드는 구조화되어 있으므로 특정 메소드의 모든 예외 핸들러는 항상 순서대로 테이블에 배열될 수 있습니다. 가능한 모든 프로그램 카운터 값에 대해 해당 프로그램에서 발생하는 예외를 처리하기 위해 선형 순서로 해당 예외 핸들러를 찾을 수 있습니다. 카운터 값.
·일치하는 catch 절을 찾을 수 없는 경우 현재 메서드는 "잡히지 않은 예외" 결과를 가져오고 마치 호출자에서 예외가 발생한 것처럼 현재 메서드의 호출자에게 이를 반환합니다. 해당 예외 처리 블록이 호출자에서 여전히 발견되지 않으면 이 오류 전파가 계속됩니다. 오류가 최상위 수준으로 전파되면 시스템은 기본 예외 처리 블록을 호출합니다.
(3) 피연산자 스택 영역 머신 명령어는 피연산자 스택에서 피연산자를 가져와서 연산하고 결과를 스택에 반환하기만 합니다. 스택 구조를 선택하는 이유는 소수의 레지스터나 비일반 레지스터(예: Intel486)만 있는 머신에서 가상 머신의 동작을 효율적으로 시뮬레이션할 수 있기 때문입니다. 피연산자 스택은 32비트입니다. 메소드에 매개변수를 전달하고 메소드로부터 결과를 수신하는 데 사용됩니다. 또한 작업 매개변수를 지원하고 작업 결과를 저장하는 데에도 사용됩니다.
예를 들어, iadd 명령어는 두 개의 정수를 추가합니다. 추가된 두 개의 정수는 피연산자 스택의 맨 위에 있는 두 단어여야 합니다. 이 두 단어는 이전 명령어에 의해 스택에 푸시되었습니다. 두 정수가 스택에서 팝되어 추가되고 결과가 피연산자 스택으로 다시 푸시됩니다.
각 기본 데이터 유형에는 필요한 작업을 수행하기 위한 특수 지침이 있습니다. 두 개의 위치가 필요한 long 및 double을 제외하고 각 피연산자에는 스택의 저장 위치가 필요합니다. 피연산자는 해당 유형에 해당하는 연산자에 의해서만 연산될 수 있습니다. 예를 들어, int 유형의 두 숫자를 long 유형의 숫자로 처리하는 경우 푸시하는 것은 불법입니다. Sun의 가상 머신 구현에서 이 제한은 바이트코드 검증기에 의해 시행됩니다. 그러나 유형에 관계없이 런타임 데이터 영역에서 작동하는 데 사용되는 몇 가지 작업(연산자 복제 및 스왑)이 있습니다.
4. 쓸모없는 유닛 컬렉션 힙
Java의 힙은 클래스의 인스턴스(객체)가 공간을 할당하는 런타임 데이터 영역입니다. Java 언어에는 가비지 수집 기능이 있습니다. 즉, 프로그래머에게 객체를 명시적으로 해제할 수 있는 기능을 제공하지 않습니다. Java는 사용되는 특정 가비지 수집 알고리즘을 규정하지 않으며 시스템의 필요에 따라 다양한 알고리즘을 사용할 수 있습니다.
5. 메소드 영역
메소드 영역은 전통적인 언어의 컴파일된 코드나 유닉스 프로세스의 텍스트 섹션과 유사합니다. 메소드 코드(컴파일된 자바 코드)와 심볼 테이블을 저장합니다. 현재 Java 구현에서는 메소드 코드가 가비지 수집 힙에 포함되지 않지만 이는 향후 버전에서 계획되어 있습니다. 각 클래스 파일에는 Java 클래스 또는 Java 인터페이스의 컴파일된 코드가 포함되어 있습니다. 클래스 파일은 자바 언어의 실행 코드 파일이라고 할 수 있다. 클래스 파일의 플랫폼 독립성을 보장하기 위해 클래스 파일의 형식도 Java Virtual Machine 사양에 자세히 설명되어 있습니다. 구체적인 내용은 Sun의 Java Virtual Machine 사양을 참조하세요.