MSIL과 Java 바이트 코드의 차이점은 무엇입니까?


답변:


75

먼저 Java 바이트 코드와 MSIL의 미묘한 차이가 초보 .NET 개발자를 귀찮게 할 것이라고 생각하지 않습니다. 둘 다 최종적으로 사용되는 물리적 머신 위의 계층 인 추상 대상 머신을 정의하는 동일한 목적을 수행합니다.

MSIL과 Java 바이트 코드는 매우 유사합니다. 사실 MSIL을 Java 바이트 코드로 변환하는 Grasshopper 라는 도구가 있습니다. 저는 Grasshopper 개발 팀의 일원이어서 제 (흐린) 지식을 공유 할 수 있습니다. .NET 프레임 워크 2.0이 나왔을 때이 문제에 대한 작업을 중단 했으므로 이러한 사항 중 일부는 더 이상 사실이 아닐 수 있습니다 (그렇다면 의견을 남겨 주시면 수정하겠습니다).

  • .NET은 일반 참조 의미 체계 ( struct) 에 따른 값 의미 체계를 가진 사용자 정의 형식을 허용합니다 .
  • .NET은 서명되지 않은 유형을 지원하므로 명령어 세트가 조금 더 풍부 해집니다.
  • Java는 바이트 코드에 메소드의 예외 사양을 포함합니다. 예외 사양은 일반적으로 컴파일러에 의해서만 적용되지만 기본 클래스 로더가 아닌 다른 클래스 로더가 사용되는 경우 JVM에서 적용 할 수 있습니다.
  • .NET 제네릭은 IL로 표현되는 반면 Java 제네릭은 유형 삭제 만 사용 합니다 .
  • .NET 속성은 Java에서 동등하지 않습니다 (여전히 사실입니까?).
  • .NET enums은 정수 유형을 둘러싼 래퍼에 지나지 않지만 Javaenums 는 거의 완전한 클래스입니다 ( 주석에 대한 Internet Friend 덕분에 ).
  • .NET에는 outref매개 변수가 있습니다.

다른 언어 차이가 있지만 대부분은 바이트 코드 수준에서 표현되지 않습니다. 예를 들어 메모리가 Java의 비 static내부 클래스 (.NET에 존재하지 않음)가 바이트 코드 기능이 아닌 경우 컴파일러는 내부 클래스의 생성자이고 외부 객체를 전달합니다. .NET 람다 식도 마찬가지입니다.


속성과 관련하여-Java 주석도 바이트 코드에 나타나도록 설정할 수 있으므로 이에 상응하는 것이 있습니다.
Oak

@Oak : Java 어노테이션은 데이터 전달 만 허용하는 반면 .NET 속성은 로직을 가질 수 있고 가장 중요한 것은 인터페이스를 구현할 수있는 완전한 클래스입니다.
Fyodor Soikin 2011-08-28

Bytecode는 또한 모든 종류의 반환 유형에 대해 별도의 반환 명령을 가지고 있습니다. 실제로 유형 안전성에 도움이되는지 알 수 없습니다.
Cecil Dishwasher

1
.NET의 값 유형이 때때로 스택에 할당 될 수 있다는 사실은 값 의미론 이 있다는 사실에 비해 사소한 중요성입니다 . 모든 가치 유형 저장 위치 인스턴스입니다. 대조적으로, Java의 모든 스토리지 위치는 원시적이거나 불규칙적 인 객체 참조입니다. 다른 유형은 없습니다.
supercat 2013-07-23

1
성능을 현명하게 비교하는 방법이 궁금하십니까? 예를 들어 MSIL은 바이트 코드를 해석하는 것이 더 빠릅니까?
Luke T O'Brien

23

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 출력과 비교할 경우 두 매우 유사하다는 것을 볼 수 있습니다 위.


2
사람이 읽고 쓸 수있는 Java 어셈블리 언어를 만들려는 시도가있었습니다. 내가 찾은 두 가지는 JasminJava Bytecode Assembler입니다
Justin

2
여기에 훨씬 더 좋은 글을 썼습니다. Jasmin과 달리 유효한 클래스 파일을 분해하고 재 어셈블 할 수 있도록 설계되었습니다. github.com/Storyyeller/Krakatau . 나는 마이크로 소프트가 표준 어셈블러를 제공하는 반면 자바 코더는 자체적으로 만들어야한다고 말하는 것이 더 정확하다고 생각한다.
Antimony

22

그들은 본질적으로 똑같은 일을하고 있으며 MSIL은 Microsoft의 Java 바이트 코드 버전입니다.

내부적으로 주요 차이점은 다음과 같습니다.

  1. 바이트 코드는 컴파일과 해석 모두를 위해 개발되었으며 MSIL은 JIT 컴파일을 위해 명시 적으로 개발되었습니다.
  2. MSIL은 여러 언어 (C # 및 VB.NET 등)를 지원하도록 개발되었으며, Bytecode는 Java 전용으로 작성되었으므로 Bytecode는 IL이 특정 .NET 언어에 대한 것보다 구문 적으로 Java와 더 유사합니다.
  3. MSIL은 값과 참조 유형 사이에 더 명확한 설명이 있습니다.

더 많은 정보와 자세한 비교는 K John Gough (포스트 스크립트 문서) 의이 기사 에서 찾을 수 있습니다.


"1. 바이트 코드는 컴파일과 해석 모두를 위해 개발되었으며 MSIL은 JIT 컴파일을 위해 명시 적으로 개발되었습니다."-Java 코드가 바이트 코드로 컴파일되고 해당 바이트 코드가 해석되는 방법에 대해 설명합니다. 제가 맞습니까? MSIL이 실행되도록 해석되지 않습니까?
Abdul

2

CIL 일명 MSIL은 사람이 읽을 수 있도록 설계되었습니다. 자바 바이트 코드는 그렇지 않습니다.

Java 바이트 코드를 존재하지 않는 (그러나 JVM이 에뮬레이트하는) 하드웨어의 기계 코드로 생각하십시오.

CIL은 어셈블리 언어와 비슷합니다. 사람이 읽을 수있는 상태에서 기계어 코드에서 한 단계 씩.


16 진 편집기가있는 한 바이트 코드는 실제로 매우 읽기 쉽습니다. 클래스와 메서드를 직접 표현하기위한 확장 기능이있는 매우 간단한 스택 기반 언어입니다. MSIL이 하위 수준 (예 : 레지스터)이라고 생각 했습니까?
Daniel Spiewak

en.wikibooks.org/wiki/… en.wikibooks.org/wiki/… 하나는 원시 CIL입니다. 다른 하나는 분해 된 바이트 코드입니다. 16 진수를 사용하면 바이트 코드를 합리적으로 읽을 수 있지만 디자인 목표는 아닙니다.
슬림형

"분해"는 정말 잘못된 단어입니다. 아마도 "디 인코딩"되었을 것입니다. 단순히 압축을 위해 .class 파일에서 바이트 코드를 읽을 수 없습니다. javap의 man 페이지에 비해 컴파일 된 클래스에서 읽을 수있는 바이트 코드를 생성하는 데 관련된 디스 어셈블리가 없습니다.
Daniel Spiewak

2

그다지 차이가 ​​없습니다. 둘 다 작성한 코드의 중간 형식입니다. 실행되면 가상 머신은 관리되는 중간 언어를 실행합니다. 즉, 가상 머신이 변수와 호출을 제어합니다. .Net과 Java에서 동일한 방식으로 실행할 수있는 지금 기억하지 못하는 언어도 있습니다.

기본적으로 같은 것을위한 또 다른 형식입니다.

편집 : 언어 발견 (Scala 제외) : FAN ( http://www.fandev.org/ ), 매우 흥미로워 보이지만 아직 평가할 시간이 없습니다.


Scala는 JVM 또는 CLR을 대상으로 컴파일하여 각각 바이트 코드 또는 MSIL을 생성 할 수 있습니다.
Daniel Spiewak

알아두면 좋겠지 만 한 달 전에 DZone을 읽을 때 다른 언어를 찾았습니다 : 찾았습니다! 내 게시물의 편집 참조
GHad

1

동의합니다. 차이는 초심자로서 충분히 이해하기 쉽습니다. 기본부터 .Net을 배우고 싶다면 Common Language Infrastructure와 Common Type System을 살펴 보는 것이 좋습니다.



1

MSIL은 자바 바이트 코드가 아니라 "자바 바이트 코드를 구성하는 명령어"와 비교해야한다고 생각합니다.

분해 된 자바 바이트 코드의 이름이 없습니다. "Java Bytecode"는 공식 문서에서 이름을 찾을 수 없으므로 비공식적 인 별칭이어야합니다. 자바 클래스 파일 디스어셈블러

클래스의 각 메소드에 대해 디스 어셈블 된 코드, 즉 Java 바이트 코드를 구성하는 명령어를 인쇄합니다. 이는 Java Virtual Machine 사양에 문서화되어 있습니다.

"Java VM 명령어"와 "MSIL"은 모두 사람이 읽을 수없는 .NET 바이트 코드와 Java 코드로 어셈블됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.