[java] 자바의 가상 머신과 CLR

MSIL과 Java 바이트 코드의 차이점 이라는 질문에 대한 후속 조치로 ? , Java Virtual Machine의 작동 방식과 주요 가상 시스템의 차이점과 유사점은 무엇입니까?.넷 프레임 워크 CLR (공용 언어 런타임)이 작동합니까?

또한 .넷 프레임 워크 CLR에 “가상 머신”또는 가상 머신의 속성이 없습니까?



답변

두 구현 사이에는 많은 유사점이 있습니다 (그리고 제 생각에는 “가상 머신”입니다).

우선, x86이나 PowerPC와 같은 최신 CPU에서 사용되는 것과 같이 “레지스터”라는 개념이없는 스택 기반 VM입니다. 모든 표현식 ((1 + 1) / 2)의 평가는 피연산자를 “스택”으로 푸시 한 다음 명령어 (추가, 나누기 등)가 피연산자를 사용해야 할 때마다 피연산자를 스택에서 팝핑하여 수행됩니다. 각 명령어는 결과를 다시 스택으로 푸시합니다.

세계의 거의 모든 CPU에 스택이 있기 때문에 가상 머신을 구현하는 편리한 방법이지만 레지스터 수는 종종 다릅니다 (일부 레지스터는 특수 목적이며 각 명령어는 다른 레지스터에서 피연산자를 기대합니다) ).

따라서 추상 머신을 모델링하려는 경우 순수 스택 기반 모델을 사용하는 것이 좋습니다.

물론 실제 기계는 그런 식으로 작동하지 않습니다. 따라서 JIT 컴파일러는 바이트 코드 연산의 “등록”을 수행해야하며, 가능한 경우 항상 피연산자와 결과를 포함하도록 실제 CPU 레지스터를 스케줄링합니다.

그래서 저는 이것이 CLR과 JVM 사이의 가장 큰 공통점 중 하나라고 생각합니다.

차이점은 …

두 구현의 흥미로운 차이점 중 하나는 CLR에 일반 유형을 만든 다음 해당 유형에 매개 변수 전문화를 적용하기위한 지침이 포함되어 있다는 것입니다. 따라서 런타임시 CLR은 List <int>를 List <String>과 완전히 다른 유형으로 간주합니다.

표지 아래에서 모든 참조 유형 전문화에 대해 동일한 MSIL을 사용하므로 (List <String>은 API 경계에서 유형 캐스트가 다른 List <Object>와 동일한 구현을 사용하지만) 각 값 유형은 고유 한 구현 (List <int>은 List <double>과 완전히 다른 코드를 생성합니다).

Java에서 제네릭 형식은 순수한 컴파일러 트릭입니다. JVM에는 유형 인수가있는 클래스에 대한 개념이 없으며 런타임시 매개 변수화 전문화를 수행 할 수 없습니다.

실제적인 관점에서 보면 일반 유형에 Java 메소드를 오버로드 할 수 없습니다. List <String> 또는 List <Date>를 허용하는지 여부 만 다른 동일한 이름을 가진 두 가지 다른 메소드를 가질 수 없습니다. 물론 CLR은 파라 메트릭 유형에 대해 알고 있기 때문에 일반 유형 전문화에서 오버로드 된 방법을 처리하는 데 아무런 문제가 없습니다.

매일 CLR과 JVM 사이에서 가장 큰 차이점이 있습니다.

다른 중요한 차이점은 다음과 같습니다.

  • CLR에는 클로저가 있습니다 (C # 델리게이트로 구현 됨). JVM은 Java 8 이후의 클로저 만 지원합니다.

  • CLR에는 코 루틴이 있습니다 (C # ‘yield’키워드로 구현 됨). JVM은 그렇지 않습니다.

  • CLR은 사용자 코드가 새로운 값 유형 (structs)을 정의 할 수 있도록하는 반면, JVM은 고정 된 값 유형 콜렉션 (바이트, short, int, long, float, double, char, boolean)을 제공하며 사용자는 새로운 참조를 정의 할 수 있습니다. 유형 (클래스).

  • CLR은 포인터 선언 및 조작을 지원합니다. JVM과 CLR 모두 메모리 관리 전략으로 엄격한 세대 압축 가비지 수집기 구현을 사용하기 때문에 특히 흥미 롭습니다. 일반적인 상황에서 엄격한 압축 GC는 포인터를 사용하는 데 어려움을 겪습니다. 한 메모리 위치에서 다른 메모리 위치로 값을 이동하면 모든 포인터 (및 포인터에 대한 포인터)가 유효하지 않기 때문입니다. 그러나 CLR은 “고정”메커니즘을 제공하므로 개발자는 CLR이 특정 포인터를 이동할 수없는 코드 블록을 선언 할 수 있습니다. 매우 편리합니다.

  • JVM에서 가장 큰 코드 단위는 ‘protected’키워드로 표시되는 ‘패키지’이거나 클래스 경로에서 jar를 지정하고 폴더처럼 처리 한 것으로 입증 된 JAR (예 : Java ARchive)입니다. 코드 CLR에서 클래스는 ‘어셈블리’로 집계되며 CLR은 어셈블리에 대한 추론 및 조작 ( “AppDomains”에로드되어 메모리 할당 및 코드 실행을위한 하위 응용 프로그램 수준 샌드 박스를 제공함)에 대한 논리를 제공합니다.

  • CIL 바이트 코드 형식 (MSIL 명령어 및 메타 데이터로 구성)은 JVM보다 명령어 유형이 적습니다. JVM에서 모든 고유 한 조작 (2 개의 int 값 추가, 2 개의 float 값 추가 등)에는 고유 한 명령이 있습니다. CLR에서 모든 MSIL 명령어는 다형성 (두 값 추가)이며 JIT 컴파일러는 피연산자의 유형을 결정하고 적절한 기계 코드를 생성합니다. 그래도 어느 것이 바람직한 전략인지는 모르겠습니다. 둘 다 장단점이 있습니다. JVM 용 HotSpot JIT 컴파일러는 더 간단한 코드 생성 메커니즘 (명령에서 이미 인코딩되었으므로 피연산자 유형을 결정할 필요가 없음)을 사용할 수 있지만 더 복잡한 바이트 코드 형식이 필요합니다. 더 많은 명령어 유형.

나는 약 10 년 동안 Java를 사용하고 JVM에 감탄했습니다.

그러나 제 생각에는 CLR은 거의 모든면에서 우수한 구현입니다.


답변

첫 번째 질문은 JVM을 .NET Framework와 비교하는 것입니다. 실제로 CLR과 비교하는 것으로 가정합니다. 그렇다면 작은 책을 쓸 수 있다고 생각합니다 ( 편집 : Benji에 이미있는 것처럼 보입니다 🙂

한 가지 중요한 차이점은 CLR이 JVM과 달리 언어 중립 아키텍처로 설계되었다는 것입니다.

또 다른 중요한 차이점은 CLR이 고유 코드와 높은 수준의 상호 운용성을 허용하도록 특별히 설계되었다는 것입니다. 즉, CLR은 기본 메모리에 액세스하고 수정할 때 안정성과 보안을 관리하고 CLR 기반 데이터 구조와 기본 데이터 구조 간의 마샬링관리해야 합니다.

두 번째 질문에 대답하기 위해“가상 머신”이라는 용어는 하드웨어 세계에서 나온 오래된 용어입니다 (예 : 1960 년대 IBM의 360 가상화). VMWare가하는 것들.

CLR은 종종 “실행 엔진”이라고합니다. 이러한 맥락에서 이는 x86 위에 IL 머신을 구현 한 것입니다. CLR의 다형성 바이트 코드와 JVM의 유형이 지정된 바이트 코드 사이에 중요한 차이점이 있다고 주장 할 수 있지만 이것은 JVM 이하는 일이기도합니다.

두 번째 질문에 대한 답은 “아니오”입니다. 그러나 실제로이 두 용어를 어떻게 정의하는지에 달려 있습니다.

편집 : JVM과 CLR의 또 다른 차이점은 JVM (버전 6)이 할당 된 메모리를 운영 체제로 되돌릴 수없는 경우 가 매우 많다는 것입니다.

예를 들어 JVM 프로세스가 시작되고 운영 체제에서 처음으로 25MB의 메모리를 할당한다고 가정 해 봅시다. 그런 다음 앱 코드는 추가 50MB가 필요한 할당을 시도합니다. JVM은 운영 체제에서 추가로 50MB를 할당합니다. 응용 프로그램 코드가 해당 메모리 사용을 중지하면 가비지 수집되고 JVM 힙 크기가 줄어 듭니다. 그러나 JVM은 특정 상황 에서만 할당 된 운영 체제 메모리를 해제 합니다. 그렇지 않으면 나머지 프로세스 수명 동안 해당 메모리가 할당 된 상태로 유지됩니다.

반면에 CLR은 할당 된 메모리를 더 이상 필요하지 않은 경우 운영 체제로 다시 해제합니다. 위의 예에서 CLR은 힙이 줄어들면 메모리를 해제했을 것입니다.


답변

CLR과 JVM은 모두 가상 머신입니다.

.NET Framework 및 JRE (Java Runtime Environment)는 해당 VM과 해당 라이브러리의 번들입니다. 라이브러리가 없으면 VM은 쓸모가 없습니다.


답변

차이점에 대한 자세한 내용은 다양한 학문 및 개인 자료에서 찾을 수 있습니다. 좋은 예가 CLR 디자인 선택 입니다.

몇 가지 구체적인 예는 다음과 같습니다.

  • CLR이 다형성 피연산자를 사용하는 “add int”와 같은 일부 하위 수준 opperand가 입력됩니다. (즉, fadd / iadd / ladd vs 그냥 추가)
  • 현재 JVM은보다 공격적인 런타임 프로파일 링 및 최적화 (예 : 핫스팟)를 수행합니다. CLR은 현재 JIT 최적화를 수행하지만 런타임 최적화는 수행하지 않습니다 (예 : 실행중인 코드 교체).
  • CLR은 가상 메소드를 인라인하지 않고 JVM은 …
  • “원시”를 넘어 CLR에서 값 유형을 지원합니다.

답변

가상 머신이 아닙니다. .net 프레임 워크는 첫 실행시 어셈블리를 원시 바이너리로 컴파일합니다.

컴퓨팅에서 동적 변환이라고도하는 JIT (Just-In-Time) 컴파일은 컴퓨터 프로그램의 런타임 성능을 향상시키는 기술입니다. JIT는 런타임 환경에서 바이트 코드 컴파일과 동적 컴파일의 두 가지 초기 아이디어를 기반으로합니다. 바이트 코드와 같이 코드를 기본적으로 실행하기 전에 런타임에 코드를 기본 기계 코드로 변환합니다. 인터프리터에 비해 성능이 향상되면 코드 블록을 번역 한 결과를 캐싱 할 수 있으며, 각 라인이나 피연산자가 충족 될 때마다 재평가하지 않고 해석됩니다 (해석 된 언어 참조). 또한 코드를 개발할 때 코드를 정적으로 컴파일하는 것보다 장점이 있습니다. 코드가 유리할 경우 코드를 다시 컴파일 할 수 있고 보안을 보장 할 수 있습니다.

Microsoft의 .NET Framework, 대부분의 Java 구현 및 가장 최근의 Actionscript 3과 같은 몇 가지 최신 런타임 환경은 고속 코드 실행을 위해 JIT 컴파일을 사용합니다.

출처 : http://en.wikipedia.org/wiki/Just-in-time_compilation

.NET 프레임 워크를 추가하면 Java와 같은 가상 머신이 포함됩니다.


답변