{
	"id": "d2084003-8e7e-4dc1-b687-3b3a884417e1",
	"created_at": "2026-04-06T01:30:21.585025Z",
	"updated_at": "2026-04-10T03:24:29.586528Z",
	"deleted_at": null,
	"sha1_hash": "cabf1bfc73fc13804c45cc12b6bb22f09d10eeef",
	"title": "Application domains - .NET Framework",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 68644,
	"plain_text": "Application domains - .NET Framework\r\nBy gewarren\r\nArchived: 2026-04-06 00:40:44 UTC\r\nNote\r\nThis article is specific to .NET Framework. It doesn't apply to newer implementations of .NET, including .NET 6\r\nand later versions.\r\nOperating systems and runtime environments typically provide some form of isolation between applications. For\r\nexample, Windows uses processes to isolate applications. This isolation is necessary to ensure that code running in\r\none application cannot adversely affect other, unrelated applications.\r\nApplication domains provide an isolation boundary for security, reliability, and versioning, and for unloading\r\nassemblies. Application domains are typically created by runtime hosts, which are responsible for bootstrapping\r\nthe common language runtime before an application is run.\r\nHistorically, process boundaries have been used to isolate applications running on the same computer. Each\r\napplication is loaded into a separate process, which isolates the application from other applications running on the\r\nsame computer.\r\nThe applications are isolated because memory addresses are process-relative; a memory pointer passed from one\r\nprocess to another cannot be used in any meaningful way in the target process. In addition, you cannot make direct\r\ncalls between two processes. Instead, you must use proxies, which provide a level of indirection.\r\nManaged code must be passed through a verification process before it can be run (unless the administrator has\r\ngranted permission to skip the verification). The verification process determines whether the code can attempt to\r\naccess invalid memory addresses or perform some other action that could cause the process in which it is running\r\nto fail to operate properly. Code that passes the verification test is said to be type-safe. The ability to verify code\r\nas type-safe enables the common language runtime to provide as great a level of isolation as the process boundary,\r\nat a much lower performance cost.\r\nApplication domains provide a more secure and versatile unit of processing that the common language runtime\r\ncan use to provide isolation between applications. You can run several application domains in a single process\r\nwith the same level of isolation that would exist in separate processes, but without incurring the additional\r\noverhead of making cross-process calls or switching between processes. The ability to run multiple applications\r\nwithin a single process dramatically increases server scalability.\r\nIsolating applications is also important for application security. For example, you can run controls from several\r\nWeb applications in a single browser process in such a way that the controls cannot access each other's data and\r\nresources.\r\nThe isolation provided by application domains has the following benefits:\r\nhttps://learn.microsoft.com/dotnet/framework/app-domains/application-domains\r\nPage 1 of 6\n\nFaults in one application cannot affect other applications. Because type-safe code cannot cause memory\r\nfaults, using application domains ensures that code running in one domain cannot affect other applications\r\nin the process.\r\nIndividual applications can be stopped without stopping the entire process. Using application domains\r\nenables you to unload the code running in a single application.\r\nNote\r\nYou cannot unload individual assemblies or types. Only a complete domain can be unloaded.\r\nCode running in one application cannot directly access code or resources from another application. The\r\ncommon language runtime enforces this isolation by preventing direct calls between objects in different\r\napplication domains. Objects that pass between domains are either copied or accessed by proxy. If the\r\nobject is copied, the call to the object is local. That is, both the caller and the object being referenced are in\r\nthe same application domain. If the object is accessed through a proxy, the call to the object is remote. In\r\nthis case, the caller and the object being referenced are in different application domains. Cross-domain\r\ncalls use the same remote call infrastructure as calls between two processes or between two machines. As\r\nsuch, the metadata for the object being referenced must be available to both application domains to allow\r\nthe method call to be JIT-compiled properly. If the calling domain does not have access to the metadata for\r\nthe object being called, the compilation might fail with an exception of type FileNotFoundException. For\r\nmore information, see Remote Objects. The mechanism for determining how objects can be accessed\r\nacross domains is determined by the object. For more information, see System.MarshalByRefObject.\r\nThe behavior of code is scoped by the application in which it runs. In other words, the application domain\r\nprovides configuration settings such as application version policies, the location of any remote assemblies\r\nit accesses, and information about where to locate assemblies that are loaded into the domain.\r\nPermissions granted to code can be controlled by the application domain in which the code is running.\r\nThis section describes the relationship between application domains and assemblies. You must load an assembly\r\ninto an application domain before you can execute the code it contains. Running a typical application causes\r\nseveral assemblies to be loaded into an application domain.\r\nThe way an assembly is loaded determines whether its just-in-time (JIT) compiled code can be shared by multiple\r\napplication domains in the process, and whether the assembly can be unloaded from the process.\r\nIf an assembly is loaded domain-neutral, all application domains that share the same security grant set can\r\nshare the same JIT-compiled code, which reduces the memory required by the application. However, the\r\nassembly can never be unloaded from the process.\r\nIf an assembly is not loaded domain-neutral, it must be JIT-compiled in every application domain in which\r\nit is loaded. However, the assembly can be unloaded from the process by unloading all the application\r\ndomains in which it is loaded.\r\nhttps://learn.microsoft.com/dotnet/framework/app-domains/application-domains\r\nPage 2 of 6\n\nThe runtime host determines whether to load assemblies as domain-neutral when it loads the runtime into a\r\nprocess. For managed applications, apply the LoaderOptimizationAttribute attribute to the entry-point method for\r\nthe process, and specify a value from the associated LoaderOptimization enumeration. For unmanaged\r\napplications that host the common language runtime, specify the appropriate flag when you call the\r\nCorBindToRuntimeEx Function method.\r\nThere are three options for loading domain-neutral assemblies:\r\nLoaderOptimization.SingleDomain loads no assemblies as domain-neutral, except Mscorlib, which is\r\nalways loaded domain-neutral. This setting is called single domain because it is commonly used when the\r\nhost is running only a single application in the process.\r\nLoaderOptimization.MultiDomain loads all assemblies as domain-neutral. Use this setting when there are\r\nmultiple application domains in the process, all of which run the same code.\r\nLoaderOptimization.MultiDomainHost loads strong-named assemblies as domain-neutral, if they and all\r\ntheir dependencies have been installed in the global assembly cache. Other assemblies are loaded and JIT-compiled separately for each application domain in which they are loaded, and thus can be unloaded from\r\nthe process. Use this setting when running more than one application in the same process, or if you have a\r\nmixture of assemblies that are shared by many application domains and assemblies that need to be\r\nunloaded from the process.\r\nJIT-compiled code cannot be shared for assemblies loaded into the load-from context, using the LoadFrom method\r\nof the Assembly class, or loaded from images using overloads of the Load method that specify byte arrays.\r\nAssemblies that have been compiled to native code by using the Ngen.exe (Native Image Generator) can be shared\r\nbetween application domains, if they are loaded domain-neutral the first time they are loaded into a process.\r\nJIT-compiled code for the assembly that contains the application entry point is shared only if all its dependencies\r\ncan be shared.\r\nA domain-neutral assembly can be JIT-compiled more than once. For example, when the security grant sets of two\r\napplication domains are different, they cannot share the same JIT-compiled code. However, each copy of the JIT-compiled assembly can be shared with other application domains that have the same grant set.\r\nWhen you decide whether to load assemblies as domain-neutral, you must make a tradeoff between reducing\r\nmemory use and other performance factors.\r\nAccess to static data and methods is slower for domain-neutral assemblies because of the need to isolate\r\nassemblies. Each application domain that accesses the assembly must have a separate copy of the static\r\ndata, to prevent references to objects in static fields from crossing domain boundaries. As a result, the\r\nruntime contains additional logic to direct a caller to the appropriate copy of the static data or method. This\r\nextra logic slows down the call.\r\nAll the dependencies of an assembly must be located and loaded when the assembly is loaded domain-neutral, because a dependency that cannot be loaded domain-neutral prevents the assembly from being\r\nhttps://learn.microsoft.com/dotnet/framework/app-domains/application-domains\r\nPage 3 of 6\n\nloaded domain-neutral.\r\nAn application domain forms an isolation boundary for security, versioning, reliability, and unloading of managed\r\ncode. A thread is the operating system construct used by the common language runtime to execute code. At\r\nruntime, all managed code is loaded into an application domain and is run by one or more managed threads.\r\nThere is not a one-to-one correlation between application domains and threads. Several threads can execute in a\r\nsingle application domain at any given time, and a particular thread is not confined to a single application domain.\r\nThat is, threads are free to cross application domain boundaries; a new thread is not created for each application\r\ndomain.\r\nAt any given time, every thread executes in an application domain. Zero, one, or multiple threads might be\r\nexecuting in any given application domain. The runtime keeps track of which threads are running in which\r\napplication domains. You can locate the domain in which a thread is executing at any time by calling the\r\nThread.GetDomain method.\r\nCulture, which is represented by a CultureInfo object, is associated with threads. You can get the culture that is\r\nassociated with the currently executing thread by using the CultureInfo.CurrentCulture property, and you can get\r\nor set the culture that is associated with the currently executing thread by using the Thread.CurrentCulture\r\nproperty. If the culture that is associated with a thread has been explicitly set by using the Thread.CurrentCulture\r\nproperty, it continues to be associated with that thread when the thread crosses application domain boundaries.\r\nOtherwise, the culture that is associated with the thread at any given time is determined by the value of the\r\nCultureInfo.DefaultThreadCurrentCulture property in the application domain in which the thread is executing:\r\nIf the value of the property is not null , the culture that is returned by the property is associated with the\r\nthread (and therefore returned by the Thread.CurrentCulture and CultureInfo.CurrentCulture properties).\r\nIf the value of the property is null , the current system culture is associated with the thread.\r\nApplication domains are usually created and manipulated programmatically by runtime hosts. However,\r\nsometimes an application program might also want to work with application domains. For example, an application\r\nprogram could load an application component into a domain to be able to unload the domain (and the component)\r\nwithout having to stop the entire application.\r\nThe AppDomain is the programmatic interface to application domains. This class includes methods to create and\r\nunload domains, to create instances of types in domains, and to register for various notifications such as\r\napplication domain unloading. The following table lists commonly used AppDomain methods.\r\nhttps://learn.microsoft.com/dotnet/framework/app-domains/application-domains\r\nPage 4 of 6\n\nAppDomain Method Description\r\nCreateDomain\r\nCreates a new application domain. It is recommended that you use an\r\noverload of this method that specifies an AppDomainSetup object. This is\r\nthe preferred way to set the properties of a new domain, such as the\r\napplication base, or root directory for the application; the location of the\r\nconfiguration file for the domain; and the search path that the common\r\nlanguage runtime is to use to load assemblies into the domain.\r\nExecuteAssembly and\r\nExecuteAssemblyByName\r\nExecutes an assembly in the application domain. This is an instance method,\r\nso it can be used to execute code in another application domain to which\r\nyou have a reference.\r\nCreateInstanceAndUnwrap\r\nCreates an instance of a specified type in the application domain, and\r\nreturns a proxy. Use this method to avoid loading the assembly containing\r\nthe created type into the calling assembly.\r\nUnload\r\nPerforms a graceful shutdown of the domain. The application domain is not\r\nunloaded until all threads running in the domain have either stopped or are\r\nno longer in the domain.\r\nNote\r\nThe common language runtime does not support serialization of global methods, so delegates cannot be used to\r\nexecute global methods in other application domains.\r\nThe unmanaged interfaces described in the common language runtime Hosting Interfaces Specification also\r\nprovide access to application domains. Runtime hosts can use interfaces from unmanaged code to create and gain\r\naccess to the application domains within a process.\r\nAn environment variable that sets the default loader optimization policy of an executable application.\r\nCOMPLUS_LoaderOptimization = 1\r\nA typical application loads several assemblies into an application domain before the code they contain can be\r\nexecuted.\r\nThe way the assembly is loaded determines whether its just-in-time (JIT) compiled code can be shared by multiple\r\napplication domains in the process.\r\nIf an assembly is loaded domain-neutral, all application domains that share the same security grant set can\r\nshare the same JIT-compiled code. This reduces the memory required by the application.\r\nIf an assembly is not loaded domain-neutral, it must be JIT-compiled in every application domain in which\r\nit is loaded and the loader must not share internal resources across application domains.\r\nhttps://learn.microsoft.com/dotnet/framework/app-domains/application-domains\r\nPage 5 of 6\n\nWhen set to 1, the COMPLUS_LoaderOptimization environment flag forces the runtime host to load all\r\nassemblies in non-domain-neutral way known as SingleDomain. SingleDomain loads no assemblies as domain-neutral, except Mscorlib, which is always loaded domain-neutral. This setting is called single domain because it is\r\ncommonly used when the host is running only a single application in the process.\r\nCaution\r\nThe COMPLUS_LoaderOptimization environment flag was designed to be used in diagnostic and test scenarios.\r\nHaving the flag turned on can cause severe slow-down and increase in memory usage.\r\nTo force all assemblies not to be loaded as domain-neutral for the IISADMIN service can be achieved by\r\nappending COMPLUS_LoaderOptimization=1 to the Environment’s Multi-String Value in the\r\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\IISADMIN key.\r\nKey = HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\IISADMIN\r\nName = Environment\r\nType = REG_MULTI_SZ\r\nValue (to append) = COMPLUS_LoaderOptimization=1\r\nSystem.AppDomain\r\nSystem.MarshalByRefObject\r\nProgramming with Application Domains and Assemblies\r\nUsing Application Domains\r\nSource: https://learn.microsoft.com/dotnet/framework/app-domains/application-domains\r\nhttps://learn.microsoft.com/dotnet/framework/app-domains/application-domains\r\nPage 6 of 6",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://learn.microsoft.com/dotnet/framework/app-domains/application-domains"
	],
	"report_names": [
		"application-domains"
	],
	"threat_actors": [
		{
			"id": "aa73cd6a-868c-4ae4-a5b2-7cb2c5ad1e9d",
			"created_at": "2022-10-25T16:07:24.139848Z",
			"updated_at": "2026-04-10T02:00:04.878798Z",
			"deleted_at": null,
			"main_name": "Safe",
			"aliases": [],
			"source_name": "ETDA:Safe",
			"tools": [
				"DebugView",
				"LZ77",
				"OpenDoc",
				"SafeDisk",
				"TypeConfig",
				"UPXShell",
				"UsbDoc",
				"UsbExe"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775439021,
	"ts_updated_at": 1775791469,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/cabf1bfc73fc13804c45cc12b6bb22f09d10eeef.pdf",
		"text": "https://archive.orkl.eu/cabf1bfc73fc13804c45cc12b6bb22f09d10eeef.txt",
		"img": "https://archive.orkl.eu/cabf1bfc73fc13804c45cc12b6bb22f09d10eeef.jpg"
	}
}