저는 .Net을 처음 사용하고 기본 사항을 먼저 이해하려고 노력하고 있습니다. MSIL과 Java 바이트 코드의 차이점은 무엇입니까?
저는 .Net을 처음 사용하고 기본 사항을 먼저 이해하려고 노력하고 있습니다. MSIL과 Java 바이트 코드의 차이점은 무엇입니까?
답변:
먼저 Java 바이트 코드와 MSIL의 미묘한 차이가 초보 .NET 개발자를 귀찮게 할 것이라고 생각하지 않습니다. 둘 다 최종적으로 사용되는 물리적 머신 위의 계층 인 추상 대상 머신을 정의하는 동일한 목적을 수행합니다.
MSIL과 Java 바이트 코드는 매우 유사합니다. 사실 MSIL을 Java 바이트 코드로 변환하는 Grasshopper 라는 도구가 있습니다. 저는 Grasshopper 개발 팀의 일원이어서 제 (흐린) 지식을 공유 할 수 있습니다. .NET 프레임 워크 2.0이 나왔을 때이 문제에 대한 작업을 중단 했으므로 이러한 사항 중 일부는 더 이상 사실이 아닐 수 있습니다 (그렇다면 의견을 남겨 주시면 수정하겠습니다).
struct
) 에 따른 값 의미 체계를 가진 사용자 정의 형식을 허용합니다 .enums
은 정수 유형을 둘러싼 래퍼에 지나지 않지만 Javaenums
는 거의 완전한 클래스입니다 ( 주석에 대한 Internet Friend 덕분에 ).out
및 ref
매개 변수가 있습니다.다른 언어 차이가 있지만 대부분은 바이트 코드 수준에서 표현되지 않습니다. 예를 들어 메모리가 Java의 비 static
내부 클래스 (.NET에 존재하지 않음)가 바이트 코드 기능이 아닌 경우 컴파일러는 내부 클래스의 생성자이고 외부 객체를 전달합니다. .NET 람다 식도 마찬가지입니다.
CIL (MSIL의 고유 이름)과 Java 바이트 코드는 서로 다른 것보다 동일합니다. 하지만 몇 가지 중요한 차이점이 있습니다.
1) CIL은 처음부터 여러 언어의 대상 역할을하도록 설계되었습니다. 따라서 서명 및 서명되지 않은 유형, 값 유형, 포인터, 속성, 대리자, 이벤트, 제네릭, 단일 루트가있는 개체 시스템 등을 포함하여 훨씬 더 풍부한 유형 시스템을 지원합니다. CIL은 전역 함수 및 마무리 호출 최적화 와 같은 초기 CLR 언어 (C # 및 VB.NET)에 필요하지 않은 기능을 지원합니다 . 비교에서 Java 바이트 코드는 Java 언어의 대상으로 설계되었으며 Java 자체에서 발견되는 많은 제약 조건을 반영합니다. Java 바이트 코드를 사용하여 C 또는 Scheme을 작성하는 것이 훨씬 더 어려울 것입니다.
2) CIL은 네이티브 라이브러리 및 관리되지 않는 코드에 쉽게 통합되도록 설계되었습니다.
3) Java 바이트 코드는 해석되거나 컴파일되도록 설계되었으며 CIL은 JIT 컴파일만을 가정하여 설계되었습니다. 즉, Mono 의 초기 구현은 JIT 대신 인터프리터를 사용했습니다.
4) CIL은 바이트 코드 형식에 직접 매핑되는 사람이 읽고 쓸 수있는 어셈블리 언어 형식을 갖도록 설계 ( 및 지정 )되었습니다. 나는 Java 바이트 코드가 (이름에서 알 수 있듯이) 기계가 읽을 수만 있음을 의미한다고 생각합니다. 물론, 자바 바이트 코드는 비교적 쉽게 원래 자바로 역 컴파일 될 수 있으며 아래와 같이 "디 어셈블"될 수도 있습니다.
JVM (대부분)은 CLR (모두)보다 고도로 최적화되어 있습니다. 따라서 원시 성능이 Java 바이트 코드를 선호하는 이유가 될 수 있습니다. 이것은 구현 세부 사항입니다.
어떤 사람들은 Java 바이트 코드가 다중 플랫폼으로 설계되었지만 CIL은 Windows 전용으로 설계되었다고 말합니다. 그렇지 않다. .NET 프레임 워크에는 몇 가지 "Windows"ism이 있지만 CIL에는 없습니다.
위의 4) 포인트의 예로서, 나는 얼마 전에 장난감 자바를 CIL 컴파일러에 썼다. 이 컴파일러에 다음 Java 프로그램을 제공하는 경우 :
class Factorial{
public static void main(String[] a){
System.out.println(new Fac().ComputeFac(10));
}
}
class Fac {
public int ComputeFac(int num){
int num_aux ;
if (num < 1)
num_aux = 1 ;
else
num_aux = num * (this.ComputeFac(num-1)) ;
return num_aux ;
}
}
내 컴파일러는 다음 CIL을 뱉어냅니다.
.assembly extern mscorlib { }
.assembly 'Factorial' { .ver 0:0:0:0 }
.class private auto ansi beforefieldinit Factorial extends [mscorlib]System.Object
{
.method public static default void main (string[] a) cil managed
{
.entrypoint
.maxstack 16
newobj instance void class Fac::'.ctor'()
ldc.i4 3
callvirt instance int32 class Fac::ComputeFac (int32)
call void class [mscorlib]System.Console::WriteLine(int32)
ret
}
}
.class private Fac extends [mscorlib]System.Object
{
.method public instance default void '.ctor' () cil managed
{
ldarg.0
call instance void object::'.ctor'()
ret
}
.method public int32 ComputeFac(int32 num) cil managed
{
.locals init ( int32 num_aux )
ldarg num
ldc.i4 1
clt
brfalse L1
ldc.i4 1
stloc num_aux
br L2
L1:
ldarg num
ldarg.0
ldarg num
ldc.i4 1
sub
callvirt instance int32 class Fac::ComputeFac (int32)
mul
stloc num_aux
L2:
ldloc num_aux
ret
}
}
이것은 ilasm.exe
실행 파일을 생성하기 위해 CIL 어셈블러에 공급할 수있는 유효한 CIL 프로그램입니다 . 보시다시피 CIL은 완전히 사람이 읽고 쓸 수있는 언어입니다. 모든 텍스트 편집기에서 유효한 CIL 프로그램을 쉽게 만들 수 있습니다.
javac
컴파일러를 사용하여 위의 Java 프로그램을 컴파일 한 다음 javap
"디 어셈블러"를 통해 결과 클래스 파일을 실행 하여 다음을 얻을 수도 있습니다.
class Factorial extends java.lang.Object{
Factorial();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3: new #3; //class Fac
6: dup
7: invokespecial #4; //Method Fac."<init>":()V
10: bipush 10
12: invokevirtual #5; //Method Fac.ComputeFac:(I)I
15: invokevirtual #6; //Method java/io/PrintStream.println:(I)V
18: return
}
class Fac extends java.lang.Object{
Fac();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public int ComputeFac(int);
Code:
0: iload_1
1: iconst_1
2: if_icmpge 10
5: iconst_1
6: istore_2
7: goto 20
10: iload_1
11: aload_0
12: iload_1
13: iconst_1
14: isub
15: invokevirtual #2; //Method ComputeFac:(I)I
18: imul
19: istore_2
20: iload_2
21: ireturn
}
javap
출력 (내 지식) 컴파일 가능한 것이 아니라 당신이 CIL 출력과 비교할 경우 두 매우 유사하다는 것을 볼 수 있습니다 위.
그들은 본질적으로 똑같은 일을하고 있으며 MSIL은 Microsoft의 Java 바이트 코드 버전입니다.
내부적으로 주요 차이점은 다음과 같습니다.
더 많은 정보와 자세한 비교는 K John Gough (포스트 스크립트 문서) 의이 기사 에서 찾을 수 있습니다.
CIL 일명 MSIL은 사람이 읽을 수 있도록 설계되었습니다. 자바 바이트 코드는 그렇지 않습니다.
Java 바이트 코드를 존재하지 않는 (그러나 JVM이 에뮬레이트하는) 하드웨어의 기계 코드로 생각하십시오.
CIL은 어셈블리 언어와 비슷합니다. 사람이 읽을 수있는 상태에서 기계어 코드에서 한 단계 씩.
그다지 차이가 없습니다. 둘 다 작성한 코드의 중간 형식입니다. 실행되면 가상 머신은 관리되는 중간 언어를 실행합니다. 즉, 가상 머신이 변수와 호출을 제어합니다. .Net과 Java에서 동일한 방식으로 실행할 수있는 지금 기억하지 못하는 언어도 있습니다.
기본적으로 같은 것을위한 또 다른 형식입니다.
편집 : 언어 발견 (Scala 제외) : FAN ( http://www.fandev.org/ ), 매우 흥미로워 보이지만 아직 평가할 시간이 없습니다.
Serge Lidin은 MSIL : Expert .NET 2.0 IL Assembler 의 세부 사항에 대한 괜찮은 책을 저술했습니다 . 또한 .NET Reflector 및 Ildasm (Tutorial)을 사용하는 간단한 방법을 살펴봄으로써 MSIL을 빠르게 선택할 수있었습니다 .
MSIL과 Java 바이트 코드의 개념은 매우 유사합니다.
MSIL은 자바 바이트 코드가 아니라 "자바 바이트 코드를 구성하는 명령어"와 비교해야한다고 생각합니다.
분해 된 자바 바이트 코드의 이름이 없습니다. "Java Bytecode"는 공식 문서에서 이름을 찾을 수 없으므로 비공식적 인 별칭이어야합니다. 자바 클래스 파일 디스어셈블러 는
클래스의 각 메소드에 대해 디스 어셈블 된 코드, 즉 Java 바이트 코드를 구성하는 명령어를 인쇄합니다. 이는 Java Virtual Machine 사양에 문서화되어 있습니다.
"Java VM 명령어"와 "MSIL"은 모두 사람이 읽을 수없는 .NET 바이트 코드와 Java 코드로 어셈블됩니다.