Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일

(시리즈 글이 6개 있습니다.)
.NET Framework: 574. .NET - 눈으로 확인하는 SharedDomain의 동작 방식
; https://www.sysnet.pe.kr/2/0/10948

.NET Framework: 575. SharedDomain과 JIT 컴파일
; https://www.sysnet.pe.kr/2/0/10949

.NET Framework: 577. CLR Profiler로 살펴보는 SharedDomain의 모듈 로드 동작
; https://www.sysnet.pe.kr/2/0/10951

.NET Framework: 578. 도메인 중립적인 어셈블리가 비-도메인 중립적인 어셈블리를 참조하는 경우
; https://www.sysnet.pe.kr/2/0/10952

닷넷: 2220. C# - .NET Framework 프로세스의 LoaderOptimization 설정을 확인하는 방법
; https://www.sysnet.pe.kr/2/0/13568

닷넷: 2221. C# - LoadContext, LoadFromContext 그리고 GAC
; https://www.sysnet.pe.kr/2/0/13569




도메인 중립적인 어셈블리가 비-도메인 중립적인 어셈블리를 참조하는 경우

도메인 중립적인 어셈블리(domain-neutral assembly)에 대해 아래의 글에서 설명을 했는데요.

.NET - 눈으로 확인하는 SharedDomain의 동작 방식
; https://www.sysnet.pe.kr/2/0/10948

위의 글을 "도메인 중립적인 어셈블리"의 기준으로 정리해 보면 다음과 같습니다.

  • SingleDomain 모드에서는 어차피 모든(mscorlib.dll을 제외한) 어셈블리가 비-도메인 중립적인 어셈블리로 로드가 되고,
  • MultiDomain 모드에서는 어차피 모든 어셈블리가 도메인 중립적인 어셈블리로 로드가 되고,
  • 반면, MultiDomainHost에서는 GAC에 설치된 어셈블리만 도메인 중립적인 어셈블리로 로드가 됨.

그렇다면, MultiDomainHost 모드에서 GAC에 설치된 어셈블리가 로드되지만, 그것이 GAC에 등록되지 않은 어셈블리를 참조하는 경우라면 어떻게 처리가 될까요?

이에 대해서는 다음의 글에 이미 답이 있습니다.

Application Domains
; https://learn.microsoft.com/en-us/dotnet/framework/app-domains/application-domains

MultiDomainHost loads strong-named assemblies as domain-neutral, if they and all their dependencies have been installed in the global assembly cache


실제로 코드로 한번 확인해 볼까요? ^^

방법은 간단합니다. ".NET - 눈으로 확인하는 SharedDomain의 동작 방식"의 소스 코드를 조금 변형할 텐데요.

우선, ConsoleApplication 프로젝트의 Main 메서드는 다음과 같이 StrongDLL 메서드만 호출합니다.

using System;

namespace ConsoleApplication1
{
    partial class Program
    {
        [LoaderOptimization(LoaderOptimization.MultiDomainHost)]
        static void Main(string[] args)
        {
            ShowProcessInfo();
            
            new StrongDLL.Class1().DoMethod(); // "StrongDLL.Class1.DoMethod called" 문자열 출력 코드 포함

            Console.WriteLine();

            AppDomain appDomain = AppDomain.CreateDomain("TestAppDomain 1");
            appDomain.DoCallBack(
                () =>
                {
                    new StrongDLL.Class1().DoMethod(); // "StrongDLL.Class1.DoMethod called" 문자열 출력 코드 포함
                }
            );

            Console.WriteLine("Press any key to exit...");
            Console.ReadLine();
        }
    }
}

그다음, WeakDLL 프로젝트는 '강력한 이름의 어셈블리'가 되도록 서명을 추가하고 StrongDLL에서 이를 참조합니다. 이후 다시 StrongDLL만 GAC에 등록하고 예제를 실행한 다음 windbg.exe의 !dumpdomain 명령어로 조사하면 됩니다. 다음은 이를 정리한 결과입니다.

0:007> !dumpdomain
--------------------------------------
Shared Domain:      00007ffb1707d720
00007ffb0b521000            C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll
00007ffb042d1000            C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll

--------------------------------------
Domain 1:           000001482b89b140
00007ffb042d1000            C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
00007ffab70240c0            c:\jit_dependency\ConsoleApplication1\bin\Debug
00007ffab7025b80            C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\StrongDLL\v4.0_1.0.0.0__677c36b6f45d74b0\StrongDLL.dll
00007ffb0b521000            C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll
00007ffab7027308            c:\jit_dependency\ConsoleApplication1\bin\Debug\WeakDLL.dll

--------------------------------------
Domain 2:           000001482b92c190
00007ffb042d1000            C:\WINDOWS\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
00007ffab7185308            c:\jit_dependency\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe
00007ffab7185c88            C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\StrongDLL\v4.0_1.0.0.0__677c36b6f45d74b0\StrongDLL.dll
00007ffab71864c0            c:\jit_dependency\ConsoleApplication1\bin\Debug\WeakDLL.dll

"LoaderOptimization.MultiDomainHost"가 정상 동작 중임을 System.dll이 "Shared Domain" 영역에 있는 것을 통해 알 수 있습니다. 반면, StrongDLL.dll은 원래는 "Shared Domain" 영역에 로드되는 것이 정상이지만 GAC에 등록되지 않은 "WeakDLL.dll"을 참조한 덕분에 "domain-neutral assembly"의 자격을 만족하지 못해 공유되지 못했습니다.

(첨부한 파일은 이 글의 예제 코드를 포함합니다.)




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 2/15/2024]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 61  62  63  64  65  66  67  68  69  70  71  72  [73]  74  75  ...
NoWriterDateCnt.TitleFile(s)
11811정성태2/11/201913276오류 유형: 510. 서버 운영체제에 NVIDIA GeForce Experience 실행 시 wlanapi.dll 누락 문제
11810정성태2/11/201911349.NET Framework: 808. .NET Profiler - GAC 모듈에서 GAC 비-등록 모듈을 참조하는 경우의 문제
11809정성태2/11/201912837.NET Framework: 807. ClrMD를 이용해 메모리 덤프 파일로부터 특정 인스턴스를 참조하고 있는 소유자 확인
11808정성태2/8/201913928디버깅 기술: 123. windbg - 닷넷 응용 프로그램의 메모리 누수 분석
11807정성태1/29/201912248Windows: 156. 가상 디스크의 용량을 복구 파티션으로 인해 늘리지 못하는 경우 [4]
11806정성태1/29/201911969디버깅 기술: 122. windbg - 덤프 파일로부터 PID와 환경 변수 등의 정보를 구하는 방법
11805정성태1/28/201913855.NET Framework: 806. C# - int []와 object []의 차이로 이해하는 제네릭의 필요성 [4]파일 다운로드1
11804정성태1/24/201911870Windows: 155. diskpart - remove letter 이후 재부팅 시 다시 드라이브 문자가 할당되는 경우
11803정성태1/10/201911370디버깅 기술: 121. windbg - 닷넷 Finalizer 스레드가 멈춰있는 현상
11802정성태1/7/201912764.NET Framework: 805. 두 개의 윈도우를 각각 실행하는 방법(Windows Forms, WPF)파일 다운로드1
11801정성태1/1/201913738개발 환경 구성: 427. Netsh의 네트워크 모니터링 기능 [3]
11800정성태12/28/201813044오류 유형: 509. WCF 호출 오류 메시지 - System.ServiceModel.CommunicationException: Internal Server Error
11799정성태12/19/201813834.NET Framework: 804. WPF(또는 WinForm)에서 UWP UI 구성 요소 사용하는 방법 [3]파일 다운로드1
11798정성태12/19/201813034개발 환경 구성: 426. vcpkg - "Building vcpkg.exe failed. Please ensure you have installed Visual Studio with the Desktop C++ workload and the Windows SDK for Desktop C++"
11797정성태12/19/201810407개발 환경 구성: 425. vcpkg - CMake Error: Problem with archive_write_header(): Can't create '' 빌드 오류
11796정성태12/19/201810097개발 환경 구성: 424. vcpkg - "File does not have expected hash" 오류를 무시하는 방법
11795정성태12/19/201812443Windows: 154. PowerShell - Zone 별로 DNS 레코드 유형 정보 조회 [1]
11794정성태12/16/20189922오류 유형: 508. Get-AzureWebsite : Request to a downlevel service failed.
11793정성태12/16/201811514개발 환경 구성: 423. NuGet 패키지 제작 - Native와 Managed DLL을 분리하는 방법 [1]
11792정성태12/11/201812298Graphics: 34. .NET으로 구현하는 OpenGL (11) - Per-Pixel Lighting파일 다운로드1
11791정성태12/11/201812270VS.NET IDE: 130. C/C++ 프로젝트의 시작 프로그램으로 .NET Core EXE를 지정하는 경우 닷넷 디버깅이 안 되는 문제 [1]
11790정성태12/11/201810623오류 유형: 507. Could not save daemon configuration to C:\ProgramData\Docker\config\daemon.json: Access to the path 'C:\ProgramData\Docker\config' is denied.
11789정성태12/10/201820487Windows: 153. C# - USB 장치의 연결 및 해제 알림을 위한 WM_DEVICECHANGE 메시지 처리 [2]파일 다운로드2
11788정성태12/4/201810465오류 유형: 506. SqlClient - Value was either too large or too small for an Int32.Couldn't store <2151292191> in ... Column
11787정성태11/29/201814428Graphics: 33. .NET으로 구현하는 OpenGL (9), (10) - OBJ File Format, Loading 3D Models파일 다운로드1
11786정성태11/29/201811118오류 유형: 505. OpenGL.NET 예제 실행 시 "Managed Debugging Assistant 'CallbackOnCollectedDelegate'" 예외 발생
... 61  62  63  64  65  66  67  68  69  70  71  72  [73]  74  75  ...