자바의 가상 머신과 CLR


140

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

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


글쎄, 좋아하고 비교하고 있다면, VM과 CLR (공용 언어 런타임)의 차이점으로 VM에 직접적인 유사점을 질문해야합니다.
cletus 2016 년

답변:


278

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

우선, 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은 거의 모든면에서 우수한 구현입니다.


73
클로저 및 생성기는 언어 수준에서 구현되며 CLR 수준의 클래스로 간단히 표시됩니다.
Curt Hagenlocher

2
힙을 처리하는 방법의 차이점은 무엇입니까? JVM은 힙 메모리를 어느 정도 완전히 관리하는 반면 CLR은 OS / 호스트 프로세스에 더 의존적입니다.
Kelly S. French

6
중요한 차이점은 Just-in-Time 컴파일 (CLR)과 (Oracle / Sun) JVM의 적응 형 최적화 간의 대비입니다.
Edwin Dalorzo

1
Java의 로컬 변수 슬롯은 레지스터와 매우 유사하게 작동합니다. 그러나 JIT가 로컬 슬롯과 스택을 실제 레지스터로 변환하기 때문에 어쨌든 모든 문제가 있습니다.
안티몬

1
@kuhajeyan 그것은 CLR이 도입되었을 때 JVM이 10 살이 기 때문입니다. IT에서 오랜 시간이 걸렸습니다. 1993 년 JVM이 출시되었을 때 심각한 경쟁자는 없었으며 CLR (2003)의 경우 산업에서 강력한 기반을 가진 성숙하고 견고한 JVM이있었습니다.
간단한 동료

25

첫 번째 질문은 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은 힙이 줄어들면 메모리를 해제했을 것입니다.


2
JVM이 할당 된 메모리를 해제하지 않는 것은 절대적으로 올바르지 않습니다. 증명을 위해이 질문에 대한 나의 답변을보십시오 : stackoverflow.com/questions/366658/…
Michael Borgwardt

JVM이 메모리를 Windows로 다시 반환하는 것을 보았습니다.
Steve Kuo

나는 JVM 6이 Ran과 Michael의 답변에 대한 링크와 함께 메모리를 해제하는 것을 매우 꺼려한다고 대답했습니다. JVM 5 에서이 동작을 보지 못했기 때문에 해당 버전이 더 꺼려졌습니다.
HTTP 410

CLR이 상위 프로세스에 의존하는 동안 JVM이 적극적으로 힙을 관리하는 방법을 다룰 수 있습니까? 내가 사용하는 특정 예는 JVM이 최대 힙 크기에 대한 런타임 인수를 가지고 있지만 기본 CLR 환경은 그렇지 않습니다. IIS에서 호스팅되는 CLR 앱이 메모리를 제한하도록 IIS를 구성 할 수 있다는 것은 사실이지만 가상 머신 정의에 IIS를 포함하는 것을 의미합니다.
Kelly S. French

@ 스티브 쿠오, 그래, 나도 보았다. 보통 오후 5시에서 오후 6시 사이입니다.
간단한 동료

11

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

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


11

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

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

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

-11

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

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

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

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

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


10
가상 머신이 성능 최적화를 위해 JIT를 사용한다고해서 더 이상 가상 머신이 아닌 것은 아닙니다. 프로그래머가 컴파일 할 때 가상 머신으로 컴파일하고 실행을 수행하기위한 구현까지 남겨 두지 만 적합 해 보인다
Allain Lalonde
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.