[제목] 쉬운 C# 코드를 어럽게 이해하기
아래와 같은 아주 단순한 C# 코드가 실행되었을 때, 내부적으로 어떠한 일이 일어날까?
// MyTest.EXE namespace MyTest { class Program { static void Main(string[] args) { MyClass c = new MyClass(); c.Run(); } } }
이 코드를 빌드하여 MyTest.EXE (x86/.NET 4.0)를 실행한다고 가정하자. C#으로 컴파일되고 빌드된 MyTest.EXE는 일반 Win32 프로그램과 다른 PE 헤더를 가지고 있으며, 프로그램이 실행되면, CLR bootstraper인 mscoree.dll 으로 점프되어 어느 버젼의 .NET Framework 을 사용하는지 체크하고, 해당 버젼의 CLR 을 사용한다.
.NET 4.0 이전에서 CLR은 mscoree.dll 과 mscorwks.dll 로 구성되어 있고, .NET 4.0 이상에서는 mscoree.dll 과 clr.dll 으로 구성되어 있다.
mscoree.dll 은 항상 %windir%\System32 디렉토리에 존재하여 CLR 구동의 시발점을 이루지만, 대부분의 CLR Implementation 은 clr.dll (혹은 mscorwks.dll)에서 구현되어 있다. 또한 clr.dll (or mscorwks.dll)은 mscorlib.dll의 많은 기능들을 호출해서 사용하기 때문에, CLR을 사용할 때, 자동으로 mscorlib.dll을 로딩하여 사용한다. 따라서 한 머신의 프로세스들 중 .NET 프로세스를 검색하기 위해서는 해당 프로세스가 mscorlib.dll 모듈을 가지고 있는지 체크하면 된다.
하나의 Managed 프로세스는 하나의 CLR을 갖는다. 한 머신에 10개의 .NET 프로그램이 실행된다면, 각각의 프로세스에 1개씩 총 10개의 clr.dll 이 Physically 존재한다 (주: Optimization 논외).
또한 하나의 프로세스는 하나의 Managed Heap을 가지며, 하나의 Garbage Collector를 갖는다. 따라서 만약 10개의 C# 프로그램이 실행되고 있다면, 10개의 GC가 존재한다.
CLR은 EXE의 Entry Point인 Main() 메서드를 호출하게 되는데, Main 메서드는 어느 클래스에나 존재할 수 있지만 반드시 Static 이어야 하고 프로그램 내에 단 1개만 존재해야 한다.
Main 메서드는 실행 전에, CLR 은 JIT Compiler를 사용하여 IL 코드를 Native 코드로 변경한다. 위의 코드에서 Main 메서드의 첫번째 문장은 MyClass 객체를 생성하는 것이다. CLR은 MyClass의 Type 정보를 가져와 CLR Managed Heap 상에 클래스 필드들로 구성된 객체를 할당한다. 필드의 생성과 더불어 MyClass 클래스 생성자(Constructor)의 문장들을 실행한다. Managed Heap에 MyClass 객체 메모리를 할당한 후, 쓰레드는 c 라는 로컬 변수를 해당 쓰레드의 스택에 4 byte만큼 생성하고 이곳에 MyClass 객체의 주소를 저장한다.
Main 메서드의 두번째 문장은 MyClass의 Run() 메서드를 실행하는 것이다. 이 문장이 실행되기 전에 CLR은 Run() 메서드를 찾아 JIT Compile 하게 된다. 메서드가 처음 실행되기 전까지 모든 메서드는 컴파일 되지 않고 MSIL 상태로 존재한다. 이것이 의미하는 것은 메서드가 호출 되기 전까지는 모든 메서드의 Native 코드가 메모리 상에 존재하지 않는다는 것이며, 따라서 디버거 상에서 메서드에 상응하는 물리적 메모리 주소에 Breakpoint를 걸 수가 없다는 것을 의미한다.
비슷한 이야기로 CLR은 초기 구동시 꼭 필요한 Assembly 만을 로딩한다. Win32 로더에서 모든 종속 DLL을 로딩하는 것과 달리 CLR 로더는 현재 메서드 실행에 필요하지 않는 어셈블리를 로딩하지 않음으로써 성능 향상을 꾀한다...
이로써 위의 간단한 C# 프로그램 실행에 대한 간단하지 않은 소개를 마친다 :-)
본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.