성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>.NET - 눈으로 확인하는 SharedDomain의 동작 방식</h1> <p> 간단히 말하면, "SharedDomain"은 도메인-중립적인 어셈블리들의 보관소입니다. 이름에 "Domain"이 붙기 때문에 혼동이 좀 오는데 정확히 말하면 SharedDomain은 AppDomain이 아닌 것입니다. 단지 그 수준이 AppDomain에서 다뤄지기 때문에 "SharedDomain"이라고 불리는 것이 자연스럽기는 합니다.<br /> <br /> 이 때문에, 닷넷 응용 프로그램에서 "SharedDomain"을 나열할 수 있는 방법이 없습니다. 단순히 AppDomain이라면 다음의 글에 나온대로,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Hot to get list of all AppDomains inside current process? ; <a target='tab' href='http://miteshsureja.blogspot.kr/2012/02/hot-to-get-list-of-all-appdomains.html'>http://miteshsureja.blogspot.kr/2012/02/hot-to-get-list-of-all-appdomains.html</a> </pre> <br /> 코드를 작성하면 확인할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; using System.Collections.Generic; using mscoree; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { AppDomain.CreateDomain("TestAppDomain 1"); DisplayAppDomains(); /* 출력 결과: ConsoleApplication1.exe TestAppDomain 1 */ } private static void DisplayAppDomains() { List<AppDomain> appDomains = new List<AppDomain>(); IntPtr handle = IntPtr.Zero; // CLR2 x86: C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscoree.tlb // CLR2 x64: C:\Windows\Microsoft.NET\Framework64\v2.0.50727\mscoree.tlb // CLR4 x86: C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscoree.tlb // CLR4 x64: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscoree.tlb // 또는, <a target='tab' href='https://www.sysnet.pe.kr/2/0/1381#icorruntimehost'>mscoree.tlb 참조 없이 ICorRuntimeHost를 정의해 직접 사용</a> CorRuntimeHost host = new CorRuntimeHost(); try { host.EnumDomains(out handle); while (true) { object domain; host.NextDomain(handle, out domain); if (domain == null) break; appDomains.Add((AppDomain)domain); } } finally { host.CloseEnum(handle); } foreach (AppDomain appDom in appDomains) { Console.WriteLine(appDom.FriendlyName); } } } } </pre> <br /> 실행해 보면 SharedDomain에 관한 어떤 정보도 얻을 수 없습니다.<br /> <br /> <hr style='width: 50%' /><br /> <a name='shared_domain'></a> <br /> 그런데, 도대체 SharedDomain이 왜 나온 것일까요?<br /> <br /> 이를 이해하려면 AppDomain을 먼저 알아야 합니다. AppDomain은, EXE 내부에서의 '닷넷의 또 다른 보안 격리 공간'입니다. 동작 방식은 간단합니다. AppDomain 공간이 있고, 그 단위로 보안 설정을 할 수 있습니다. 따라서, 신뢰하지 않는 웹 사이트로부터 DLL을 다운로드 받았다면 낮은 권한을 갖는 AppDomain을 생성해 그 안에서 해당 DLL을 로드해 실행해 볼 수 있습니다. 덕분에, 신뢰할 수 없는 DLL의 코드를 안전하게 실행해 볼 수 있는 것입니다.<br /> <br /> AppDomain이 사용되는 대표적인 응용 프로그램이 바로 ASP.NET입니다. ASP.NET은 서로 다른 '웹 응용 프로그램'을 하나의 w3wp.exe에서 실행할 수 있게 해주는데, 이때 각각의 '웹 응용 프로그램'은 별도의 AppDomain 별로 할당되어 보안상 격리되기 때문에 하나의 EXE를 공유하지만 서로 침범할 수 없어 'security'를 보장 받을 수 있습니다.<br /> <br /> 데스크톱 응용 프로그램에서도 유용한 경우가 있습니다. 가령, 윈도우 폼 응용 프로그램의 경우 3rd-party 컨트롤을 로드할 수 있도록 /extension 이라는 폴더를 제공한다고 가정했을 때 그 폴더에 있는 DLL을 별도의 AppDomain을 만들어 그 안에서 로드한 다음 리플렉션을 이용해 '확장 컨트롤 규약'을 만족하는지 확인하는 용도로 사용하곤 합니다. 이렇게 밖에 할 수 없는 이유는, DLL이 AppDomain 별로 로드/언로드가 가능하기 때문입니다. 따라서 만약 별도의 AppDomain을 만들지 않고, 현재의 AppDomain에서 /extension 폴더에 포함된 DLL을 로드해 버리면 그것이 '확장 컨트롤 규약'을 만족하지 않아도 언로드할 수 없으므로 계속 들고 있게 됩니다. (해당 파일이 잠기는 것은 덤으로 따라오는 고통입니다.)<br /> <br /> 이런저런 이유로, AppDomain은 알아두면 꽤나 유용한데요. 문제는, AppDomain은 '격리 공간'이기 때문에 하나의 동일한 어셈블리라고 해도 각각의 AppDomain에 모두 로드되어야 한다는 단점이 있습니다. 당연하겠지만, 이렇게 되면 동일한 DLL을 AppDomain 별로 가져야 하기 때문에 JIT 컴파일을 비롯해서 메모리 공간의 낭비로 이어집니다. 마이크로소프트는 이런 단점을 해결하기 위해 3가지 유형의 어셈블리 공유 방식을 CLR 수준에서 지원합니다.<br /> <br /> <ul> <li><span style='color: blue; font-weight: bold'>SingleDomain</span> (기본값): mscorlib.dll을 제외한 모든 어셈블리를 개별 AppDomain에 로드한다. mscorlib.dll은 SharedDomain에 로드되고 다른 AppDomain들은 SharedDomain에 로드된 mscorlib.dll을 공유한다. </li> <br /> <li><span style='color: blue; font-weight: bold'>MultiDomainHost</span> (ASP.NET 웹 응용 프로그램의 기본값): mscorlib.dll뿐만 아니라 GAC에 등록된 어셈블리를 모두 SharedDomain에 로드해 공유한다. 그 이외의 어셈블리들은 모두 개별 AppDomain에 로드한다. 과거에 닷넷 1.x 환경의 경우, GAC에 등록되어 있지 않았더라도 강력한 이름의 어셈블리(strong-named assembly)라면 모두 SharedDomain에 로드했지만 2.0부터는 GAC의 어셈블리만으로 정책이 변경됨.</li> <br /> <li><span style='color: blue; font-weight: bold'>MultiDomain</span>: 모든 어셈블리를 SharedDomain에 로드하고 공유한다.</li> </ul> <br /> 즉, SharedDomain에 공유할 어셈블리를 보관할 수 있게 해서 AppDomain 마다 중복 로드되는 문제를 해결한 것입니다. 그리고, 이렇게 SharedDomain에 보관되는 어셈블리를 일컬어 "도메인 중립적인 어셈블리(Domain neutral assembly)"라고 부릅니다.<br /> <br /> 재미있는 것은, 어셈블리 스스로는 도메인 중립적으로 로드하라고 명시할 수 없다는 점입니다. 단지, 도메인 중립적으로 로드할지에 대한 정책이 AppDomain에 지정되는 것입니다.<br /> <br /> 참고로, 이 값들은 mscorlib.dll에 다음과 같이 정의되어 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > namespace System { using System.Runtime.InteropServices; [Serializable, ComVisible(true)] public enum LoaderOptimization { [Obsolete("This method has been deprecated. Please use Assembly.Load() instead. http://go.microsoft.com/fwlink/?linkid=14202")] DisallowBindings = 4, [Obsolete("This method has been deprecated. Please use Assembly.Load() instead. http://go.microsoft.com/fwlink/?linkid=14202")] DomainMask = 3, <span style='color: blue; font-weight: bold'>MultiDomain = 2,</span> <span style='color: blue; font-weight: bold'>MultiDomainHost = 3,</span> NotSpecified = 0, <span style='color: blue; font-weight: bold'>SingleDomain = 1</span> } } </pre> <br /> 사실상 쓰는 값은 SingleDomain = 1, MultiDomain = 2, MultiDomainHost = 3 입니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 그럼, 재미있는 코딩과 함께 직접 눈으로 확인을 해볼까요? ^^<br /> <br /> 이를 위해 <a target='tab' href='http://stackoverflow.com/questions/3058110/what-are-the-steps-for-making-domain-neutral-assemblies'>LoaderOptimization 모드를 지정할 수 있는 방법</a>을 사용해야 하는데 크게 다음의 3가지 방식이 있습니다.<br /> <br /> <ul> <li>실행 파일 진입 메서드(보통 Main 메서드)에 <a target='tab' href='https://learn.microsoft.com/en-us/dotnet/api/system.loaderoptimizationattribute'>LoaderOptimization 특성</a>으로 설정</li> <li>AppDomain 생성 시 <a target='tab' href='https://learn.microsoft.com/en-us/dotnet/api/system.appdomainsetup.loaderoptimization'>AppDomainSetup.LoaderOptimization</a> 속성에 설정</li> <li><a target='tab' href='https://learn.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/corbindtoruntimeex-function'>CorBindToRuntimeEx</a>을 이용해 직접 CLR 호스팅을 하는 경우 3번째 startupFlags 인자로 전달</li> </ul> <br /> 이 중에서 가장 쉬운 방법은 첫 번째 방법이므로, 저 역시 예제를 간단히 하기 위해 그것을 사용하겠습니다.<br /> <br /> 우선, 콘솔 프로그램을 하나 만들고 다음과 같이 Main 메서드를 작성합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; namespace ConsoleApplication1 { partial class Program { <span style='color: blue; font-weight: bold'>[LoaderOptimization(LoaderOptimization.SingleDomain)]</span> static void Main(string[] args) { Console.WriteLine(AppDomain.CurrentDomain.SetupInformation.LoaderOptimization); // 출력 결과: SingleDomain } } } </pre> <br /> 기본값이 LoaderOptimization.SingleDomain이어서 지정하지 않아도 되지만 어쨌든 명시를 했습니다. 그리고 SharedDomain에 보관되는 DLL을 확인하기 위해 라이브러리 프로젝트를 2개 만드는데요. 하나는 일반 DLL로, 다른 하나는 GAC에 등록되는 강력한 이름을 가진 DLL로 만듭니다.<br /> <br /> <ul> <li>ConsoleApplication1: 콘솔 프로그램, StrongDLL과 WeakDLL 라이브러리를 참조</li> <li>StrongDLL: GAC에 등록해서 테스트할 목적의 DLL 라이브러리 (빌드 후, GAC 등록)</li> <li>WeakDLL: GAC에 등록되지 않는 일반 DLL 라이브러리</li> </ul> <br /> Main 메서드 내의 코드는 테스트를 위해 AppDomain을 하나 만들고 다음과 같이 채워줍니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [LoaderOptimization(LoaderOptimization.SingleDomain)] static void Main(string[] args) { <span style='color: blue; font-weight: bold'>new StrongDLL.Class1().DoMethod();</span> // "StrongDLL.Class1.DoMethod called" 문자열 출력 코드 포함 <span style='color: blue; font-weight: bold'>new WeakDLL.Class1().DoMethod();</span> // "WeakDLL.Class1.DoMethod called" 문자열 출력 코드 포함 // AppDomain에 로드된 어셈블리 목록 출력 WeakDLL.Class1.DisplayAssemblies(AppDomain.CurrentDomain); <span style='color: blue; font-weight: bold'>AppDomain appDomain = AppDomain.CreateDomain</span>("TestAppDomain 1"); appDomain.DoCallBack( () => { // 이하 코드는 생성된 "TestAppDomain 1" 내에서 수행됨. <span style='color: blue; font-weight: bold'>new StrongDLL.Class1().DoMethod();</span> // "StrongDLL.Class1.DoMethod called" 문자열 출력 코드 포함 <span style='color: blue; font-weight: bold'>new WeakDLL.Class1().DoMethod();</span> // "WeakDLL.Class1.DoMethod called" 문자열 출력 코드 포함 // AppDomain에 로드된 어셈블리 목록 출력 WeakDLL.Class1.DisplayAssemblies(AppDomain.CurrentDomain); } ); Console.WriteLine("Press any key to exit..."); Console.ReadLine(); } </pre> <br /> 즉, Main 메서드가 포함된 Default Domain (콘솔의 경우 AppDomain 이름이 실행 파일명)과 새롭게 생성한 "TestAppDomain 1"에서 DLL 2개를 사용하고 있습니다.<br /> <br /> 일단, 저 상태에서 실행해 보면 다음과 같은 출력 결과를 볼 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > StrongDLL.Class1.DoMethod called WeakDLL.Class1.DoMethod called [ConsoleApplication1.exe] mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null <span style='color: blue; font-weight: bold'>StrongDLL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=677c36b6f45d74b0 WeakDLL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</span> System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 StrongDLL.Class1.DoMethod called WeakDLL.Class1.DoMethod called [TestAppDomain 1] mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null <span style='color: blue; font-weight: bold'>StrongDLL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=677c36b6f45d74b0 WeakDLL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</span> </pre> <br /> 아쉽게도 AppDomain.GetAssemblies() 메서드의 결과로는 해당 AppDomain에 올라온 DLL 목록만을 볼 수 있을 뿐, SharedDomain 관련 여부는 알 수 없습니다. 따라서 그 부분을 파악하고 싶다면 windbg.exe와 sos.dll 확장의 도움을 받아야 합니다.<br /> <br /> 다음은 SingleDomain 유형으로 설정되었을 때의 !dumpdomain 상황을 보여줍니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 0:007> <span style='color: blue; font-weight: bold'>.loadby sos clr</span> 0:007> <span style='color: blue; font-weight: bold'>!dumpdomain</span> -------------------------------------- System Domain: 00007ffb1707dcf0 LowFrequencyHeap: 00007ffb1707e268 HighFrequencyHeap: 00007ffb1707e2f8 StubHeap: 00007ffb1707e388 Stage: OPEN Name: None -------------------------------------- <span style='color: blue; font-weight: bold'>Shared Domain: 00007ffb1707d720</span> LowFrequencyHeap: 00007ffb1707e268 HighFrequencyHeap: 00007ffb1707e2f8 StubHeap: 00007ffb1707e388 Stage: OPEN Name: None Assembly: 000001acdb1fbd70 [C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll] ClassLoader: 000001acdb1e4d50 Module Name <span style='color: blue; font-weight: bold'>00007ffb042d1000 C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll</span> -------------------------------------- <span style='color: blue; font-weight: bold'>Domain 1: 000001acdb18ae60</span> LowFrequencyHeap: 000001acdb18b658 HighFrequencyHeap: 000001acdb18b6e8 StubHeap: 000001acdb18b778 Stage: OPEN SecurityDescriptor: 000001acdb18ce80 Name: ConsoleApplication1.exe Assembly: 000001acdb1fbd70 [C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll] ClassLoader: 000001acdb1e4d50 SecurityDescriptor: 000001acdb1f2f50 Module Name <span style='color: blue; font-weight: bold'>00007ffb042d1000 C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll</span> Assembly: 000001acdb1fab70 [C:\shared_domain\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe] ClassLoader: 000001acdb209dd0 SecurityDescriptor: 000001acdb1f2c80 Module Name 00007ffab70440c0 C:\shared_domain\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe Assembly: 000001acdb1faed0 [C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\StrongDLL\v4.0_1.0.0.0__677c36b6f45d74b0\StrongDLL.dll] ClassLoader: 000001acdb20db80 SecurityDescriptor: 000001acdb1f3400 Module Name <span style='color: blue; font-weight: bold'>00007ffab7045b80 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\StrongDLL\v4.0_1.0.0.0__677c36b6f45d74b0\StrongDLL.dll</span> Assembly: 000001acdb1fb7d0 [C:\shared_domain\ConsoleApplication1\bin\Debug\WeakDLL.dll] ClassLoader: 000001acdb20dc30 SecurityDescriptor: 000001acdb1f3130 Module Name <span style='color: blue; font-weight: bold'>00007ffab70463a8 C:\shared_domain\ConsoleApplication1\bin\Debug\WeakDLL.dll</span> Assembly: 000001acdb1fb110 [C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll] ClassLoader: 000001acdb21e630 SecurityDescriptor: 000001acdb1f2d70 Module Name 00007ffb0b521000 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll -------------------------------------- <span style='color: blue; font-weight: bold'>Domain 2: 000001acdb215e80</span> LowFrequencyHeap: 000001acdb216678 HighFrequencyHeap: 000001acdb216708 StubHeap: 000001acdb216798 Stage: OPEN SecurityDescriptor: 000001acdb1fc320 Name: TestAppDomain 1 Assembly: 000001acdb1fbd70 [C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll] ClassLoader: 000001acdb1e4d50 SecurityDescriptor: 000001acdb1f36d0 Module Name <span style='color: blue; font-weight: bold'>00007ffb042d1000 C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll</span> Assembly: 000001acdb1faa50 [C:\shared_domain\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe] ClassLoader: 000001acdb230dd0 SecurityDescriptor: 000001acdb22e630 Module Name 00007ffab71a5308 C:\shared_domain\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe Assembly: 000001acdb1fb8f0 [C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\StrongDLL\v4.0_1.0.0.0__677c36b6f45d74b0\StrongDLL.dll] ClassLoader: 000001acdb2332e0 SecurityDescriptor: 000001acdb22f800 Module Name <span style='color: blue; font-weight: bold'>00007ffab71a5c88 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\StrongDLL\v4.0_1.0.0.0__677c36b6f45d74b0\StrongDLL.dll</span> Assembly: 000001acdb1fbb30 [C:\shared_domain\ConsoleApplication1\bin\Debug\WeakDLL.dll] ClassLoader: 000001acdb229110 SecurityDescriptor: 000001acdb22e270 Module Name <span style='color: blue; font-weight: bold'>00007ffab71a64b0 C:\shared_domain\ConsoleApplication1\bin\Debug\WeakDLL.dll</span> </pre> <br /> LoaderOptimization.SingleDomain 모드에서는 mscorlib.dll만 SharedDomain에 로드되고 나머지 어셈블리들은 각자의 AppDomain에 중복 로드된다고 했습니다. 정말 그렇게 나오는지 mscorlib.dll을 뽑아서 살펴보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Shared Domain: 00007ffb1707d720 <span style='color: blue; font-weight: bold'>00007ffb042d1000</span> C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll Domain 1: 000001acdb18ae60 <span style='color: blue; font-weight: bold'>00007ffb042d1000</span> C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll Domain 2: 000001acdb215e80 <span style='color: blue; font-weight: bold'>00007ffb042d1000</span> C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll </pre> <br /> mscorlib.dll의 모듈 주소가 00007ffb042d1000로 동일하게 나옵니다. 게다가 SharedDomain 목록에 포함된 것은 mscorlib.dll만이 유일합니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 이번에는, 모든 DLL을 SharedDomain으로 올리는 LoaderOptimization.MultiDomain 모드를 테스트하기 위해 Main 메서드에 지정된 특성을 다음과 같이 바꾸고 <br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [LoaderOptimization(<span style='color: blue; font-weight: bold'>LoaderOptimization.MultiDomain</span>)] static void Main(string[] args) { // ...[생략]... } </pre> <br /> 실행한 후 windbg의 !dumpdomain 출력 결과를 (System Domain 제외, 약간 정리해서) 보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > -------------------------------------- Shared Domain: 00007ffb1707d720 00007ffb042d1000 C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll 00007ffab7004178 C:\shared_domain\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe 00007ffb0b521000 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll 00007ffab7004e98 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\StrongDLL\v4.0_1.0.0.0__677c36b6f45d74b0\StrongDLL.dll 00007ffab7005570 C:\shared_domain\ConsoleApplication1\bin\Debug\WeakDLL.dll -------------------------------------- Domain 1: 0000016c3663ac70 Name: ConsoleApplication1.exe 00007ffb042d1000 C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll 00007ffab7004178 C:\shared_domain\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe 00007ffb0b521000 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll 00007ffab7004e98 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\StrongDLL\v4.0_1.0.0.0__677c36b6f45d74b0\StrongDLL.dll 00007ffab7005570 C:\shared_domain\ConsoleApplication1\bin\Debug\WeakDLL.dll -------------------------------------- Domain 2: 0000016c366c9060 Name: TestAppDomain 1 00007ffb042d1000 C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll 00007ffab7004178 C:\shared_domain\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe 00007ffb0b521000 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll 00007ffab7004e98 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\StrongDLL\v4.0_1.0.0.0__677c36b6f45d74b0\StrongDLL.dll 00007ffab7005570 C:\shared_domain\ConsoleApplication1\bin\Debug\WeakDLL.dll </pre> <br /> 예상했던 대로 사용중인 모든 DLL들이 Shared Domain에 올라와 있고 개별 AppDomain에 표시된 모든 DLL들의 모듈 주소가 같습니다. (즉, 공유되었습니다.)<br /> <br /> 마지막으로 GAC에 등록된 어셈블리만을 SharedDomain으로 올리는 LoaderOptimization.MultiDomainHost 모드를 테스트 해보겠습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [LoaderOptimization(<span style='color: blue; font-weight: bold'>LoaderOptimization.MultiDomainHost</span>)] static void Main(string[] args) { // ...[생략]... } </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > -------------------------------------- Shared Domain: 00007ffb1707d720 00007ffb0b521000 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\<span style='color: blue; font-weight: bold'>System.dll</span> 00007ffab7024780 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\StrongDLL\v4.0_1.0.0.0__677c36b6f45d74b0\<span style='color: blue; font-weight: bold'>StrongDLL.dll</span> 00007ffb042d1000 C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\<span style='color: blue; font-weight: bold'>mscorlib.dll</span> -------------------------------------- Domain 1: 000002482958ae60 Name: ConsoleApplication1.exe 00007ffb042d1000 C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll 00007ffab70340c0 C:\shared_domain\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe 00007ffab7024780 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\StrongDLL\v4.0_1.0.0.0__677c36b6f45d74b0\StrongDLL.dll 00007ffab7035cb8 C:\shared_domain\ConsoleApplication1\bin\Debug\WeakDLL.dll 00007ffb0b521000 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll -------------------------------------- Domain 2: 000002482961c280 Name: TestAppDomain 1 00007ffb042d1000 C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll 00007ffab7195308 C:\shared_domain\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe 00007ffab7024780 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\StrongDLL\v4.0_1.0.0.0__677c36b6f45d74b0\StrongDLL.dll 00007ffab7195dc0 C:\shared_domain\ConsoleApplication1\bin\Debug\WeakDLL.dll </pre> <br /> 문서와 동일하게, GAC에 등록된 어셈블리만 Shared Domain에 목록이 올라와 있고 그 외의 어셈블리들은 개별 AppDomain에 있습니다. 그래서 같은 사용자 DLL이지만, StrongDLL.dll은 SharedDomain에 포함된 반면, WeakDLL.dll은 개별 AppDomain에 로드된 것입니다.<br /> <br /> (<a target='tab' href='http://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1013&boardid=331301885'>첨부한 파일은 이 글의 예제 코드를 포함</a>합니다.)<br /> <br /> <hr style='width: 50%' /><br /> <br /> 아울러, 다음의 문서도 읽어보실 것을 권장합니다. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Application Domains ; <a target='tab' href='https://learn.microsoft.com/en-us/dotnet/framework/app-domains/application-domains'>https://learn.microsoft.com/en-us/dotnet/framework/app-domains/application-domains</a> Domain Neutral Assemblies ; <a target='tab' href='https://learn.microsoft.com/en-us/archive/blogs/junfeng/domain-neutral-assemblies'>https://learn.microsoft.com/en-us/archive/blogs/junfeng/domain-neutral-assemblies</a> </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1565
(왼쪽의 숫자를 입력해야 합니다.)