How does .NET locate the dll of the namespace I'm using?
yeah, we do mention the path in /referene:c:\program files** but after building & deploying and when the software is installed on some user's machine. It may not be at the same path as I (developer) mentioned it would be. I mean it could be some where else right?
So, how does .NET find it?
How does .NET know at the runtime what all namespaces are there in a dll?
What if the user has the same dll but he renamed it? Does .net fails to load it then?
You can see the various probing steps in action if you run fuslogvw.exe (from the .NET SDK) and enable logging of all binds to disk. You will be able to see the various paths that .NET CLR uses to resolve assembly references. The rule of thumb though is to try the Global Assembly Cache first then check the local directory along with a bunch of other alternate paths.
Technically, there aren't any namespaces in the DLL.
On CLR level, there are no namespaces at all, only full class names. A CLR class name can consist of an arbitrarily long sequence of any Unicode characters - e.g. ##$% would be a perfectly fine class name, as far as CLR is concerned.
Now, by convention (CLS, to be specific), class names are restricted to certain Unicode characters (alphanumerics and _, and a bunch of other exotic Unicode categories - see the spec for more info) and dot, and dot is used to denote namespaces. This is purely a convention between compilers (and other tools).
So, whenever an assembly references some type for any reason, it simply uses its complete CLR name, such as System.String. But there is more - in fact, it uses a fully qualified name, which includes an assembly as well. You can see those if you look at ildasm output - they look something like [mscorlib]System.String, so the runtime knows where to look.
In other words, CLR really sees assembly mscorlib.dll having class System.String, and assembly B.exe referencing that class as [mscorlib]System.String. Your using statement doesn't generate any code in the output DLL/EXE on its own; it's there just so that you don't have to write System.String all the time.
It's compiler's job to translate your code saying String, in a scope of a using System; statement, in a project which references mscorlib.dll, to [mscorlib]System.String. It's all done at compile-time. The only thing CLR does at runtime is resolving mscorlib to locate the actual mscorlib.dll on disk (and the other answer explains how exactly that happens).
Assembly location rules are explained in http://msdn.microsoft.com/en-us/library/yx7xezcf.aspx
The names of assemblies and namespaces are unrelated concepts.
Compiled assembly reference other assemblies by containing their name.
When an assembly is loaded, its references are loaded by searching for the name as described here. The most common location for assemblies are the Global Assembly Cache of a machine, and the base directory of an application.
After loading the assembly and all its references (and the references of the references, etc) the runtime loads the required types from the assemblies.
For example, if you use the type String as in
using System;
...
String x = "Hello World";
the C# compiler looks up String and resolves it to the System.String type in the mscorlib assembly, and transforms the code to something similar to this:
[mscorlib]System.String x = "Hello World";
So when the statement is executed the runtime knows both the full name of the type System.String and the name of the assembly that contains the type.
The only answer that answers the question is Pavel Minaev's comment.
Take the following basic C# Program.
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello");
}
}
}
The compiler resolves Console by looking at all the assemblies that are referenced using /r: in the compilation command line. If there are more than 2 definitions of Console for the global namespace in the assemblies that are referenced, which is extended using the using statements, then there will be a compiler error -- to resolve this you would need to explicitly use System.Console to indicate the System namespace rather than the global namespace.
Similarly, if you use System.Console, then if there is more than one definition of System.Console in the assemblies that are referenced then there is a compiler error. This would either be 2 classes in the System namespace with the same name, which would need to be resolved by the programmer by renaming that, or defining a class called System in the global namespace that has been extended by using System, where System.Console is a subclass, which would be impossible to distinguish even if it were using global::
Once it has found a referenced assembly that contains the definition, it can now work with that definition and produce the correct IL.
When you compile this simple application, you get the following in ildasm:
// Metadata version: v4.0.30319
.assembly extern /*23000001*/ mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly /*20000001*/ ConsoleApp1
{
.custom /*0C000001:0A000001*/ instance void [mscorlib/*23000001*/]System.Runtime.CompilerServices.CompilationRelaxationsAttribute/*01000001*/::.ctor(int32) /* 0A000001 */ = ( 01 00 08 00 00 00 00 00 )
.custom /*0C000002:0A000002*/ instance void [mscorlib/*23000001*/]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute/*01000002*/::.ctor() /* 0A000002 */ = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom /*0C000003:0A000003*/ instance void [mscorlib/*23000001*/]System.Diagnostics.DebuggableAttribute/*01000003*/::.ctor(valuetype [mscorlib/*23000001*/]System.Diagnostics.DebuggableAttribute/*01000003*//DebuggingModes/*01000004*/) /* 0A000003 */ = ( 01 00 07 01 00 00 00 00 )
.custom /*0C000004:0A000004*/ instance void [mscorlib/*23000001*/]System.Reflection.AssemblyTitleAttribute/*01000005*/::.ctor(string) /* 0A000004 */ = ( 01 00 0B 43 6F 6E 73 6F 6C 65 41 70 70 31 00 00 ) // ...ConsoleApp1..
.custom /*0C000005:0A000005*/ instance void [mscorlib/*23000001*/]System.Reflection.AssemblyDescriptionAttribute/*01000006*/::.ctor(string) /* 0A000005 */ = ( 01 00 00 00 00 )
.custom /*0C000006:0A000006*/ instance void [mscorlib/*23000001*/]System.Reflection.AssemblyConfigurationAttribute/*01000007*/::.ctor(string) /* 0A000006 */ = ( 01 00 00 00 00 )
.custom /*0C000007:0A000007*/ instance void [mscorlib/*23000001*/]System.Reflection.AssemblyCompanyAttribute/*01000008*/::.ctor(string) /* 0A000007 */ = ( 01 00 00 00 00 )
.custom /*0C000008:0A000008*/ instance void [mscorlib/*23000001*/]System.Reflection.AssemblyProductAttribute/*01000009*/::.ctor(string) /* 0A000008 */ = ( 01 00 0B 43 6F 6E 73 6F 6C 65 41 70 70 31 00 00 ) // ...ConsoleApp1..
.custom /*0C000009:0A000009*/ instance void [mscorlib/*23000001*/]System.Reflection.AssemblyCopyrightAttribute/*0100000A*/::.ctor(string) /* 0A000009 */ = ( 01 00 12 43 6F 70 79 72 69 67 68 74 20 C2 A9 20 // ...Copyright ..
20 32 30 32 31 00 00 ) // 2021..
.custom /*0C00000A:0A00000A*/ instance void [mscorlib/*23000001*/]System.Reflection.AssemblyTrademarkAttribute/*0100000B*/::.ctor(string) /* 0A00000A */ = ( 01 00 00 00 00 )
.custom /*0C00000B:0A00000B*/ instance void [mscorlib/*23000001*/]System.Runtime.InteropServices.ComVisibleAttribute/*0100000C*/::.ctor(bool) /* 0A00000B */ = ( 01 00 00 00 00 )
.custom /*0C00000C:0A00000C*/ instance void [mscorlib/*23000001*/]System.Runtime.InteropServices.GuidAttribute/*0100000D*/::.ctor(string) /* 0A00000C */ = ( 01 00 24 64 66 65 35 65 36 32 61 2D 65 61 31 33 // ..$dfe5e62a-ea13
2D 34 66 37 64 2D 39 36 39 32 2D 37 35 39 39 64 // -4f7d-9692-7599d
31 31 66 31 63 36 61 00 00 ) // 11f1c6a..
.custom /*0C00000D:0A00000D*/ instance void [mscorlib/*23000001*/]System.Reflection.AssemblyFileVersionAttribute/*0100000E*/::.ctor(string) /* 0A00000D */ = ( 01 00 07 31 2E 30 2E 30 2E 30 00 00 ) // ...1.0.0.0..
.custom /*0C00000E:0A00000E*/ instance void [mscorlib/*23000001*/]System.Runtime.Versioning.TargetFrameworkAttribute/*0100000F*/::.ctor(string) /* 0A00000E */ = ( 01 00 1C 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B // ....NETFramework
2C 56 65 72 73 69 6F 6E 3D 76 34 2E 36 2E 31 01 // ,Version=v4.6.1.
00 54 0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 // .T..FrameworkDis
70 6C 61 79 4E 61 6D 65 14 2E 4E 45 54 20 46 72 // playName..NET Fr
61 6D 65 77 6F 72 6B 20 34 2E 36 2E 31 ) // amework 4.6.1
.hash algorithm 0x00008004
.ver 1:0:0:0
}
.module ConsoleApp1.exe
// MVID: {5BC9CD36-3807-4339-8AAD-6E73A42CE87B}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00020003 // ILONLY 32BITREQUIRED
// Image base: 0x00000000003B0000
.class /*02000002*/ private auto ansi beforefieldinit ConsoleApp1.Program
extends [mscorlib/*23000001*/]System.Object/*01000010*/
{
.method /*06000001*/ private hidebysig static
void Main(string[] args) cil managed
// SIG: 00 01 01 1D 0E
{
.entrypoint
// Method begins at RVA 0x2050
// Code size 13 (0xd)
.maxstack 8
IL_0000: /* 00 | */ nop
IL_0001: /* 72 | (70)000001 */ ldstr "Hello" /* 70000001 */
IL_0006: /* 28 | (0A)00000F */ call void [mscorlib/*23000001*/]System.Console/*01000011*/::WriteLine(string) /* 0A00000F */
IL_000b: /* 00 | */ nop
IL_000c: /* 2A | */ ret
} // end of method Program::Main
.method /*06000002*/ public hidebysig specialname rtspecialname
instance void .ctor() cil managed
// SIG: 20 00 01
{
// Method begins at RVA 0x205e
// Code size 8 (0x8)
.maxstack 8
IL_0000: /* 02 | */ ldarg.0
IL_0001: /* 28 | (0A)000010 */ call instance void [mscorlib/*23000001*/]System.Object/*01000010*/::.ctor() /* 0A000010 */
IL_0006: /* 00 | */ nop
IL_0007: /* 2A | */ ret
} // end of method Program::.ctor
} // end of class ConsoleApp1.Program
As can be seen, the assembly that contains the type in a certain namespace that is being referenced is resolved by the compiler, so the runtime does not need to search the manifests of all of the dependent assemblies. Instead, looks for the assembly in the square brackets and then uses the manifest in the image that is currently running to acquire more details. It then searches the global assembly cache if it is strong named and then it searches certain directories for a .config file or for the assemblies themselves. On Mono, these directories are the directory that contains the image that is currently being executed on the virtual machine and the MONO_PATH environment variable -- it searches the GAC last.
The runtime dynamically loads assemblies when an object of type of a class in the assembly is first referenced as opposed to instantiated – the instantiation is deferred. When you use DllImport, the .dll is also dynamically loaded when it is required by the runtime. For internal calls, you would need to internally call your own native function from C# that dynamically loads a .dll using LoadLibrary and then get GetProcAddress to make the internal call binding, before making the real call.
An extern alias can be used to access an assembly that is referenced using /r: explicitly: /r:GridV1=grid.dll and then extern alias GridV1 and then GridV1::Namespace.Class. The :: operator accesses a member of an aliased namespace, which is either the global alias, an extern alias, or an alias created by the using alias directive. These alias directives do not extend the global namespace unlike the regular using or using static.
Related
I am using Xamarin.Forms 4.6 and the LibVLCsharp library to show videos on Android devices.
I ran some of the sample apps and got a couple to run but those sample apps are using Xamarin 3.2.
The problem is as soon as the Play method is called the app crashes hard and doesn't even throw an exception.
I get this in the output window:
06-19 12:37:29.044 D/ViewRootImpl#cb7f4a7MainActivity: ViewPostIme pointer 0
06-19 12:37:29.113 D/ViewRootImpl#cb7f4a7MainActivity: ViewPostIme pointer 1
06-19 12:37:29.128 D/Mono (10562): DllImport searching in: 'libvlc' ('libvlc.so').
06-19 12:37:29.128 D/Mono (10562): Searching for 'libvlc_media_player_play'.
06-19 12:37:29.128 D/Mono (10562): Probing 'libvlc_media_player_play'.
06-19 12:37:29.128 D/Mono (10562): Found as 'libvlc_media_player_play'.
06-19 12:37:29.129 D/Mono (10562): DllImport searching in: 'libvlc' ('libvlc.so').
06-19 12:37:29.129 D/Mono (10562): Searching for 'libvlc_media_player_get_media'.
06-19 12:37:29.129 D/Mono (10562): Probing 'libvlc_media_player_get_media'.
06-19 12:37:29.129 D/Mono (10562): Found as 'libvlc_media_player_get_media'.
Thread started: #11
06-19 12:37:29.166 D/Mono (10562): Requesting loading reference 5 (of 11) of /storage/emulated/0/Android/data/com.companyname.xamarintestapp/files/.override/LibVLCSharp.Forms.dll
06-19 12:37:29.166 D/Mono (10562): Loading reference 5 of /storage/emulated/0/Android/data/com.companyname.xamarintestapp/files/.override/LibVLCSharp.Forms.dll asmctx DEFAULT, looking for Java.Interop, Version=0.1.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065
06-19 12:37:29.166 D/Mono (10562): Assembly Ref addref LibVLCSharp.Forms[0x7ab54d3e80] -> Java.Interop[0x7a9f22e800]: 14
=================================================================
Native Crash Reporting
Got a SEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
No native Android stacktrace (see debuggerd output).
=================================================================
Basic Fault Address Reporting
Memory around native instruction pointer (0x7a90c94e68):0x7a90c94e58 20 8b 46 f9 ff 03 00 f9 e1 83 00 91 22 00 a0 72 .F........."..r
0x7a90c94e68 08 00 40 f9 33 00 a0 72 08 19 40 f9 00 01 3f d6 ..#.3..r..#...?.
0x7a90c94e78 a0 03 00 34 28 a9 00 b0 20 8b 46 f9 08 d9 1a 91 ...4(... .F.....
0x7a90c94e88 00 e4 00 6f 00 1d 08 4e f3 0b 00 b9 e0 03 81 3c ...o...N.......<
===================================================
Managed Stacktrace:
domain required for stack walk=================================================================
06-19 12:37:29.167 W/.xamarintestap(10562): 0xebadde09 skipped times: 0
06-19 12:37:29.170 F/libc (10562): Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 10643 (Thread-17), pid 10562 (.xamarintestapp)
Anyone have any ideas on why this is happening? I attached a sample test to this post which demonstrates what I am seeing.
A link to the test app is here: http://www.filedropper.com/xamarintestapp2
Missing Core.Initialize() call
While trying to get back results from a separate thread, my app simply stops working and exits, with available information I've been able to write this code
public async override Task<IQueryable<Entry>> FindAsync(string inputText)
{
var resultingEntries = await Task.Run(() =>
{
// The heavy stuff starts here, in anew thread.
using (var realm = Realm.GetInstance(DbConfig))
{
// All data
var bgHaystack = realm.All<Entry>();
// Because realm doesn't support some of the LINQ operations on not stored fields (Content)
// the set of entries is converted to a IEnumerable.
IEnumerable<Entry> subset = bgHaystack;
// This is where the search gets actually done
subset = subset.Where(entry => entry.Content.ToLower().StartsWith(inputText));
// Extracts ids
var foundEntryIds = ExtractIdsFromEntries(subset);
// Select entries
var foundEntries = FindingManyMatches(bgHaystack, foundEntryIds.ToArray());
return ThreadSafeReference.Create(foundEntries);
}
});
var results = Realm.GetInstance(DbConfig).ResolveReference(resultingEntries);
return results;
}
And everything works just fine, except for the second to last line where I want to get the resulting object, do you have any idea on what's wrong here and how to solve this issue?
Stack trace:
Native Crash Reporting
=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=================================================================
No native Android stacktrace (see debuggerd output).
=================================================================
Basic Fault Address Reporting
=================================================================
Memory around native instruction pointer (0x7cdcb67c70):0x7cdcb67c60 c0 03 5f d6 c8 02 80 52 e0 03 08 2a c0 03 5f d6 .._....R...*.._.
0x7cdcb67c70 08 00 40 79 09 3d 0e 53 08 3d 00 12 69 01 00 35 ..#y.=.S.=..i..5
0x7cdcb67c80 09 01 13 12 2a 01 00 32 0b fc 5f 48 7f 21 29 6b ....*..2.._H.!)k
0x7cdcb67c90 a1 00 00 54 0a 7c 0b 48 8b ff ff 35 e0 03 1f 2a ...T.|.H...5...*
================================================
05-08 23:09:47.037 D/Mono (25933): Found as 'shared_realm_resolve_object_reference'.=================
Managed Stacktrace:
=================================================================
at <unknown> <0xffffffff>
at NativeMethods:resolve_query_reference <0x00007>
at Realms.SharedRealmHandle:ResolveReference <0x00243>
at Realms.Realm:ResolveReference <0x0008f>
at <FindAsync>d__9:MoveNext <0x0062f>
at MoveNextRunner:InvokeMoveNext <0x000f3>
at System.Threading.ExecutionContext:RunInternal <0x003af>
at System.Threading.ExecutionContext:Run <0x0006b>
at MoveNextRunner:Run <0x00193>
at <>c:<.cctor>b__7_0 <0x0009b>
at <>c__DisplayClass2_0:<Post>b__0 <0x00093>
at RunnableImplementor:Run <0x000bb>
at Java.Lang.IRunnableInvoker:n_Run <0x000c3>
at Android.Runtime.DynamicMethodNameCounter:20 <0x000af>
at Android.Runtime.DynamicMethodNameCounter:20 <0x000e3>
=================================================================
05-08 23:09:47.037 D/Mono (25933): DllImport searching in: 'realm-wrappers' ('librealm-wrappers.so').
05-08 23:09:47.037 D/Mono (25933): Searching for 'shared_realm_resolve_list_reference'.
05-08 23:09:47.037 D/Mono (25933): Probing 'shared_realm_resolve_list_reference'.
05-08 23:09:47.037 D/Mono (25933): Found as 'shared_realm_resolve_list_reference'.
05-08 23:09:47.037 D/Mono (25933): DllImport searching in: 'realm-wrappers' ('librealm-wrappers.so').
05-08 23:09:47.037 D/Mono (25933): Searching for 'shared_realm_resolve_query_reference'.
05-08 23:09:47.037 D/Mono (25933): Probing 'shared_realm_resolve_query_reference'.
05-08 23:09:47.037 D/Mono (25933): Found as 'shared_realm_resolve_query_reference'.
05-08 23:09:47.040 F/libc (25933): Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x188 in tid 25933 (panyname.dosham), pid 25933 (panyname.dosham)
05-08 23:09:47.061 D/Mono (25933): DllImport searching in: 'realm-wrappers' ('librealm-wrappers.so').
05-08 23:09:47.062 D/Mono (25933): Searching for 'query_destroy'.
05-08 23:09:47.062 D/Mono (25933): Probing 'query_destroy'.
05-08 23:09:47.062 D/Mono (25933): Found as 'query_destroy'.
05-08 23:09:47.259 I/panyname.dosha(25933): ProcessProfilingInfo new_methods=0 is saved saved_to_disk=0 resolve_classes_delay=8000
Looks like it is a bug, removing the
using (var realm = Realm.GetInstance(DbConfig))
solved the issue, i.e.
var resultingEntries = await Task.Run(() =>
{
var allEntries = Realm.GetInstance(DbConfig).All<Entry>();
// Because realm doesn't support some of the LINQ operations on not stored fields (Content)
// the set of entries is converted to a IEnumerable.
IEnumerable<Entry> subset = allEntries;
// This is where the search gets actually done
subset = subset.Where(entry => entry.Content.ToLower().StartsWith(inputText));
// Extracts ids
var foundEntryIds = ExtractIdsFromEntries(subset);
// Select entries
var foundEntries = FindingManyMatches(allEntries, foundEntryIds.ToArray());
var foundEntriesCount = foundEntries.Count();
return ThreadSafeReference.Create(foundEntries);
});
var results = Realm.GetInstance(DbConfig).ResolveReference(resultingEntries);
return results;
I have a .NET windows service application with a memory leak.
Overview:
The service connects to another service via TCP, and writes data to a SQL server database. The service normally runs between 100 and 300 MB depending on how much data it has queued up. It generally takes 3 + days before I noticed the service's memory is getting out of hand, and will have a Out Of Memory exception within 2 weeks of running.
I think the issue might be related to a massive number of objects that are not leaving the finalization queue.
I have attached to the service with Windbg and run the !FinalizationQueue command and get:
0:029> !finalizequeue
SyncBlocks to be cleaned up: 0
Free-Threaded Interfaces to be released: 0
MTA Interfaces to be released: 0
STA Interfaces to be released: 0
generation 0 has 0 finalizable objects (32c69ea4->32c69ea4)
generation 1 has 266 finalizable objects (32c69a7c->32c69ea4)
generation 2 has 23191 finalizable objects (32c53020->32c69a7c)
Ready for finalization 5124616 objects (32c69ea4->33ff66c4)
Statistics for all finalizable objects (including all objects ready for finalization):
MT Count TotalSize Class Name
73e0b3ec 1 16 System.Threading.Gen2GcCallback
73e16648 1 20 Microsoft.Win32.SafeHandles.SafeFileMappingHandle
73e165f8 1 20 Microsoft.Win32.SafeHandles.SafeViewOfFileHandle
73df36f4 1 20 System.Security.Cryptography.SafeKeyHandle
...
73e2b208 36 720 Microsoft.Win32.SafeHandles.SafeWaitHandle
731a7754 33 924 System.Net.SafeFreeCredential_SECURITY
731a2d58 10 1240 System.Diagnostics.PerformanceCounter
59d01074 28 1680 System.Management.ManagementObject
73e2a8c4 175 2100 System.WeakReference
70b0385c 48 6144 System.Data.SqlClient.SqlConnection
731b2e94 201 6432 System.ComponentModel.Container
70b03ef4 86 14104 System.Data.SqlClient.SqlCommand
70b06014 712 14240 System.Data.SqlClient.SNIPacket
73e15b34 1248 24960 System.Threading.ThreadPoolWorkQueueThreadLocals
73e26c74 2238 44760 Microsoft.Win32.SafeHandles.SafeRegistryHandle
**73e2e424 1903 98956 System.Threading.Thread
70b08530 986 295800 System.Data.DataTable
70b08b08 20802 2662656 System.Data.DataColumn
6fab76dc 379139 7582780 System.Transactions.SafeIUnknown
73e30008 4740054 208562376 System.Threading.ReaderWriterLock**
I ran: !DumpHeap on the ReaderWriterLock and got:
0:029> !DumpHeap /d -mt 73e30008
... Omitted
Address MT Size
00c51f58 73e30008 44
00c5644c 73e30008 44
00c5ebc0 73e30008 44
00c81420 73e30008 44
... Omitted
I was trying to find out why there are millions of ReaderWriterLocks in the finalization queue, so I ran GCRoot on several of the addresses from the dumpheap and get:
0:029> !GCRoot 00c5ebc0
HandleTable:
005413cc (pinned handle)
-> 01d133c8 System.Object[]
-> 00cd2820 System.Diagnostics.TraceSource
-> 00cd29ac System.Diagnostics.SourceSwitch
-> 00c71704 System.Diagnostics.SwitchElementsCollection
-> 00c7177c System.Configuration.ConfigurationValues
-> 00c5fbec System.Configuration.RuntimeConfigurationRecord
-> 00c5ebec System.Configuration.RuntimeConfigurationRecord
-> 00c5eb74 System.Configuration.Internal.InternalConfigRoot
-> **00c5ebc0** System.Threading.ReaderWriterLock
Found 1 unique roots (run '!GCRoot -all' to see all roots).
I ran !do on the lock address:
0:029> !do 00c5ebc0
Name: System.Threading.ReaderWriterLock
MethodTable: 73e30008
EEClass: 73a6ff54
Size: 44(0x2c) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
MT Field Offset Type VT Attr Value Name
73e2c00c 4001890 4 System.IntPtr 1 instance 0 _hWriterEvent
73e2c00c 4001891 8 System.IntPtr 1 instance 0 _hReaderEvent
73e2c00c 4001892 c System.IntPtr 1 instance 0 _hObjectHandle
73e2f6bc 4001893 10 System.Int32 1 instance 0 _dwState
73e2f6bc 4001894 14 System.Int32 1 instance 0 _dwULockID
73e2f6bc 4001895 18 System.Int32 1 instance 3 _dwLLockID
73e2f6bc 4001896 1c System.Int32 1 instance 0 _dwWriterID
73e2f6bc 4001897 20 System.Int32 1 instance 3 _dwWriterSeqNum
73e2c494 4001898 24 System.Int16 1 instance 0 _wWriterLevel
I wanted to see all the modules that had the ReaderWriterLock loaded, so I ran the Name2EE command on the System.Threading.ReaderWriterLock and got:
0:029> !Name2EE * System.Threading.ReaderWriterLock
Module: 739f1000
Assembly: mscorlib.dll
Token: 020004c8
MethodTable: 73e30008
EEClass: 73a6ff54
Name: System.Threading.ReaderWriterLock
Module: 00573fbc
Assembly: J_ToDatabase.exe
Module: 00574e0c
Assembly: JLibrary.dll
Module: 72f31000
Assembly: System.ServiceProcess.dll
Module: 72f71000
Assembly: System.dll
Module: 00578034
Assembly: JConfigHelper.dll
Module: 72141000
Assembly: System.Windows.Forms.dll
Module: 72da1000
Assembly: System.Drawing.dll
Module: 0057ac64
Assembly: JLib.dll
Module: 0057ba1c
Assembly: J_DB_Deploy.dll
Module: 0057c8a0
Assembly: JModel.dll
Module: 03571d7c
Assembly: JLicense.dll
Module: 71211000
Assembly: System.Xml.dll
Module: 03574074
Assembly: JSecureBase.dll
Module: 03574804
Assembly: JSecure, Version=17.13.21.82, Culture=neutral
Module: 71921000
Assembly: System.Configuration.dll
Module: 71a11000
Assembly: System.Core.dll
Module: 0357539c
Assembly:
Module: 03575c7c
Assembly: JSecure, Version=17.13.21.82, Culture=neutral
Module: 59ce1000
Assembly: System.Management.dll
Module: 03577b2c
Assembly: Localization.dll
Module: 03578b6c
Assembly: JSecure, Version=17.13.21.82, Culture=neutral
Module: 03579070
Assembly:
Module: 03579840
Assembly: JSecure, Version=17.13.21.82, Culture=neutral
Module: 709f1000
Assembly: System.Data.dll
Module: 702f1000
Assembly: System.Security.dll
Module: 70661000
Assembly: System.Numerics.dll
Module: 6faa1000
Assembly: System.Transactions.dll
Module: 6f4e1000
Assembly: System.EnterpriseServices.dll
Module: 6f471000
Assembly: System.EnterpriseServices.Wrapper.dll
Module: 043a2cbc
Assembly: JTPlib.dll
Module: 043a3af8
Assembly: JStore.Core.dll
Module: 043a4920
Assembly: SystemEventArgsUtility.dll
Module: 043a7378
Assembly: JMAFLibrary.dll
Module: 043ace28
Assembly: J_A_Library.dll
Module: 03c0afb8
Assembly: DatabaseSharedLibrary.dll
Module: 03ab1c24
Assembly:
Module: 03ab23f8
Assembly: JSecure, Version=17.13.21.82, Culture=neutral
Module: 03ab28f8
Assembly:
Module: 03ab30c8
Assembly: JSecure, Version=17.13.21.82, Culture=neutral
Module: 03ab35c8
Assembly:
...
**NOTE JSecure showed up like this over 800 times!**
...
Module: 03ab3d98
Assembly: JSecure, Version=17.13.21.82, Culture=neutral
Assembly: JSecure, Version=17.13.21.82, Culture=neutral This seems to be part of the problem because it showed up over 800 times, I omitted all instances from the results because it was too much text.
Notes about JSecure, it is a dll that manages the licensing of my service. The dll is loaded into my service via
System.Reflection.Assembly.Load
method because of security reasons.
The two major questions I have are
What is causing JSecure at least seem to be loaded over 800 times?
What is causing millions of System.Threading.ReaderWriterLock to be left in the finalization queue?
Any clues on how to track down this memory leak further?
Update 1
Per suggestion in the comment, I have dug into the finalizer thread more.
When I run !Threads, I get 1905 results, though I think most of the threads are also in the finalizerqueue, there are only about 20 active threads. When I change to the Finalizer thread, and run kb to get the stack trace, I get:
0:002> kb
# ChildEBP RetAddr Args to Child
00 02e2f0e0 75892cc7 000003d4 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
01 02e2f154 75892c02 000003d4 ffffffff 00000000 KERNELBASE!WaitForSingleObjectEx+0x99
02 02e2f168 75ff9839 000003d4 ffffffff 0075d59c KERNELBASE!WaitForSingleObject+0x12
03 (Inline) -------- -------- -------- -------- combase!MTAThreadWaitForCall+0x43 [d:\blue\com\combase\dcomrem\channelb.cxx # 5657]
04 02e2f198 7609d524 006e1568 006e5808 02e2f404 combase!MTAThreadDispatchCrossApartmentCall+0x1ed [d:\blue\com\combase\dcomrem\chancont.cxx # 193]
05 (Inline) -------- -------- -------- -------- combase!CRpcChannelBuffer::SwitchAptAndDispatchCall+0x33a2 [d:\blue\com\combase\dcomrem\channelb.cxx # 5052]
06 02e2f2ec 75f7caea 0075d59c 02e2f404 02e2f3cc combase!CRpcChannelBuffer::SendReceive2+0x62d [d:\blue\com\combase\dcomrem\channelb.cxx # 4796]
07 (Inline) -------- -------- -------- -------- combase!ClientCallRetryContext::SendReceiveWithRetry+0x2e [d:\blue\com\combase\dcomrem\callctrl.cxx # 1090]
08 (Inline) -------- -------- -------- -------- combase!CAptRpcChnl::SendReceiveInRetryContext+0x81 [d:\blue\com\combase\dcomrem\callctrl.cxx # 715]
09 02e2f34c 75fc1789 0075d59c 02e2f404 02e2f3cc combase!DefaultSendReceive+0x9e [d:\blue\com\combase\dcomrem\callctrl.cxx # 671]
0a (Inline) -------- -------- -------- -------- combase!CAptRpcChnl::SendReceive+0x38 [d:\blue\com\combase\dcomrem\callctrl.cxx # 752]
0b 02e2f3b0 7609a010 0075d59c 02e2f404 02e2f3cc combase!CCtxComChnl::SendReceive+0x248 [d:\blue\com\combase\dcomrem\ctxchnl.cxx # 735]
0c 02e2f3d4 77865769 0073be14 02e2f430 77865740 combase!NdrExtpProxySendReceive+0x5c [d:\blue\com\combase\ndr\ndrole\proxy.cxx # 2017]
0d 02e2f3ec 778e6c1b ee46341f 0073be14 02e2f850 rpcrt4!NdrpProxySendReceive+0x29
0e 02e2f818 76099e1e 75f6d8f8 75f72ff0 02e2f850 rpcrt4!NdrClientCall2+0x22b
0f 02e2f838 75f7c46f 02e2f850 00000008 02e2f8d8 combase!ObjectStublessClient+0x6c [d:\blue\com\combase\ndr\ndrole\i386\stblsclt.cxx # 215]
10 02e2f848 75fc1c07 0073be14 02e2f888 006ce0a8 combase!ObjectStubless+0xf [d:\blue\com\combase\ndr\ndrole\i386\stubless.asm # 171]
11 02e2f8d8 75fc3024 006ce098 74d08aa9 02e2f99c combase!CObjectContext::InternalContextCallback+0x1e4 [d:\blue\com\combase\dcomrem\context.cxx # 4428]
12 02e2f92c 74d086b1 006ce0a8 74d08aa9 02e2f99c combase!CObjectContext::ContextCallback+0xbc [d:\blue\com\combase\dcomrem\context.cxx # 4332]
13 02e2fa24 74d08782 74d081d7 02e2fab4 ec1c2444 clr!CtxEntry::EnterContext+0x243
14 02e2fa5c 74d087c3 74d081d7 02e2fab4 00000000 clr!RCW::EnterContext+0x3a
15 02e2fa78 74d085a0 006ce150 ec1c2490 752963e8 clr!RCWCleanupList::ReleaseRCWListInCorrectCtx+0xc0
16 02e2fad4 74cd19c5 ec1c253c 7529562c 00000000 clr!RCWCleanupList::CleanupAllWrappers+0x14d
17 02e2fb24 74cd1bc8 006ae690 00000001 ec1c24e0 clr!SyncBlockCache::CleanupSyncBlocks+0xd0
18 02e2fb3c 74cd3ad8 ec1c2550 02e2fc58 02e2fcd0 clr!Thread::DoExtraWorkForFinalizer+0x7f
19 02e2fb84 74d09b0e 02e2fcd0 006bdcc8 02e2fcd0 clr!WKS::GCHeap::FinalizerThreadWorker+0x232
1a 02e2fb98 74d09b78 ec1c2224 02e2fcd0 00000000 clr!ManagedThreadBase_DispatchInner+0x67
1b 02e2fc3c 74d09c45 ec1c2280 00000000 00000040 clr!ManagedThreadBase_DispatchMiddle+0x7e
1c 02e2fc98 74c852e2 ec1c230c 74c8517c 00000000 clr!ManagedThreadBase_DispatchOuter+0x5b
1d 02e2fd14 74cd5f91 00000000 00000000 00000000 clr!WKS::GCHeap::FinalizerThreadStart+0x1a0
1e 02e2fdb4 77917c04 006bd910 77917be0 ee68e49d clr!Thread::intermediateThreadProc+0x4d
1f 02e2fdc8 77cdab8f 006bd910 ee10b078 00000000 kernel32!BaseThreadInitThunk+0x24
20 02e2fe10 77cdab5a ffffffff 77cbffdf 00000000 ntdll!__RtlUserThreadStart+0x2f
21 02e2fe20 00000000 74cd5f48 006bd910 00000000 ntdll!_RtlUserThreadStart+0x1b
I tested Dotfuscator with some of my DLLs written in C#.
It seemed it works really well on .NET environment, so this time I tried them with Unity3D. Those simple DLLs were just coded only with simple standard C# classes and methods, no reflection, no LINQ, no other custom or 3rd party APIs including Unity's. But failed to make them work in my Unity3d project, while original pure DLLs which aren't obfuscated were working fine.
After struggling for a few hours, I decided to test with new simple projects. Below is all I got in C#, there are no other code, no other references at all.
[System.Reflection.Obfuscation(Feature = "renaming", Exclude = true)]
public class Class1
{
[System.Reflection.Obfuscation(Feature = "renaming", Exclude = true)]
public static int Get()
{
return 123;
}
}
After compiling this to DLL, I put it in an EMPTY project on Unity3D Editor and played, and it worked well. But when I gave another try after obfuscating the DLL with Dotfuscator, it stopped saying "InvalidProgramException: Invalid IL code in Class1:Get (): IL_000c: pop".
As you can see above, I added attributes which prevent the code from being renamed, and of course, I could see in Reflector, the name of both class and method weren't actually renamed.
Yesterday I newly registered and downloaded the evaluation version of the latest Dotfuscator Professional Edition 4.21.0 from PreEmptive's site. I compiled both on Visual Studio 2008 and 2015 with .NET 3.5, also tried with all different Solution Platforms. The version of Unity is 5.3.4f1.
My guess now is Dotfuscator only works with MSIL, not Mono 2.X which Unity3D internally uses.
Am I right? Is there anyone using Dotfuscator with Unity3D or Mono well?
[EDIT]
I checked IL code using ILDasm, don't understand what's going on, but interesting to see a bunch of code is modified.
Before applying Dotfuscator
.method public hidebysig static int32 Get() cil managed
{
.custom instance void [mscorlib]System.Reflection.ObfuscationAttribute::.ctor() = ( 01 00 02 00 54 0E 07 46 65 61 74 75 72 65 08 72 // ....T..Feature.r
65 6E 61 6D 69 6E 67 54 02 07 45 78 63 6C 75 64 // enamingT..Exclud
65 01 ) // e.
// Code Size 6 (0x6)
.maxstack 8
IL_0000: ldc.i4 0x75bcd15
IL_0005: ret
} // end of method Class1::Get
After applying Dotfuscator
.method public hidebysig static int32 Get() cil managed
{
// Code Size 127 (0x7f)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldc.i4 0x993
IL_0005: stloc V_0
IL_0009: ldloca V_0
IL_000d: ldind.i4
IL_000e: ldc.i4 0x993
IL_0013: stloc V_0
IL_0017: ldloca V_0
IL_001b: ldind.i4
IL_001c: ceq
IL_001e: switch (
IL_002f,
IL_004c,
IL_002f)
IL_002f: br.s IL_003e
IL_0031: ldc.i4.0
IL_0032: stloc V_0
IL_0036: ldloca V_0
IL_003a: ldind.i4
IL_003b: pop
IL_003c: br.s IL_004a
IL_003e: ldc.i4.0
IL_003f: stloc V_0
IL_0043: ldloca V_0
IL_0047: ldind.i4
IL_0048: br.s IL_003b
IL_004a: nop
IL_004b: nop
IL_004c: ldc.i4 0x1
IL_0051: stloc V_0
IL_0055: ldloca V_0
IL_0059: ldind.i4
IL_005a: br.s IL_0068
IL_005c: ldc.i4.0
IL_005d: stloc V_0
IL_0061: ldloca V_0
IL_0065: ldind.i4
IL_0066: br.s IL_0068
IL_0068: brfalse.s IL_006a
IL_006a: ldc.i4.0
IL_006b: stloc V_0
IL_006f: ldloca V_0
IL_0073: ldind.i4
IL_0074: brfalse IL_0079
IL_0079: ldc.i4 0x75bcd15
IL_007e: ret
} // end of method Class1::Get
UPDATE: As of version 6.0, Dotfuscator Professional no longer supports Unity. (See changelog for 6.0.0-beta). It continues to support Mono. The original answer follows.
Yes, Dotfuscator Professional Edition supports Mono and Unity. The reason you're seeing differences in the IL is due to the Control Flow obfuscation that Professional Edition provides. This is a distinct from the Renaming feature from which you have excluded your identifiers.
By default, Dotfuscator uses as many Control Flow transforms as it can get away with on the .NET Framework (i.e., Microsoft's implementation). However, some of these transforms are not compatible with Mono. Dotfuscator provides an option to disable such transforms.
After loading your Dotfuscator project in the GUI, this option can be found on the Settings tab, under "Advanced", named "Use only Mono-compatible transforms". Set this option to "Yes", then save and rebuild the project.
If that is still giving you problems, you can disable Control Flow entirely to see if that fixes the problem. This is also on the Settings tab, under "Features", "Disable Control Flow". Set this option to "Yes", then save and rebuild the project.
Full disclosure: I work for the Dotfuscator team at PreEmptive Solutions. If you have more questions, keep in mind that evaluation users like yourself also have full access to PreEmptive support.
We have a Visual Studio 2008 solution with 58 projects. One project targets the 3.5 runtime while the other 57 target 3.0. The solution builds fine in Visual Studio 2008. I open the solution in Visual Studio 2010 and proceed through the Upgrade project Wizard. When prompted, I decline targeting the 4.0 runtime and stick with the currently selected runtime. The conversion completes with no errors.
When attempting to build I get a large number of the following two warnings:
"The primary reference [AssemblyX] could not be resolved because it has an indirect dependency on the .NET Framework assembly "CrystalDecisions.Enterprise.Framework, Version=11.5.3300.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" which has a higher version "11.5.3300.0" than the version "10.5.3700.0" in the current target framework.
C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets"
and
"The primary reference [AssemblyY] could not be resolved because it has an indirect dependency on the .NET Framework assembly "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" which has a higher version "4.0.0.0" than the version "2.0.0.0" in the current target framework.
C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets"
I looked at the manifest for an assembly where this error occurs:
// Metadata version: v4.0.30319
.assembly extern System.Web
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
.ver 2:0:0:0
}
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0 //***********Why is this targeting the 4.0?
}
.assembly extern System.Xml
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 2:0:0:0
}
.assembly extern [SomeAssembly1]
{
.ver 1:0:0:0
}
.assembly extern [SomeAssembly2]
{
.publickeytoken = (A7 E6 CA C5 42 3F 9E A9 ) // ....B?..
.ver 3:1:30307:0
}
.assembly extern [SomeAssembly3]
{
.publickeytoken = (A7 E6 CA C5 42 3F 9E A9 ) // ....B?..
.ver 3:1:30307:0
}
.assembly extern mscorlib as mscorlib_6
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 2:0:0:0
}
.assembly extern System
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 2:0:0:0
}
.assembly extern Relo.Profile.Client
{
.ver 1:0:0:0
}
.assembly extern PRERS.Logging
{
.publickeytoken = (A7 E6 CA C5 42 3F 9E A9 ) // ....B?..
.ver 3:1:30307:0
}
.assembly extern Microsoft.Practices.EnterpriseLibrary.Logging
{
.publickeytoken = (74 B5 57 D6 49 41 67 26 ) // t.W.IAg&
.ver 3:1:0:0
}
I looked at the refernces that SomeAssembly1, SomeAssembly2, SomeAssembly3 (and the entire solution) make and I can't find anything that is targetting 4.0.
I've searched for solutions/discussions on the internet and none of the workarounds I have found seem to work for me.
http://social.msdn.microsoft.com/Forums/en/msbuild/thread/516647ee-dccf-49ee-959a-00b1fc098eeb
http://connect.microsoft.com/VisualStudio/feedback/details/571860/assemblies-targetting-net-3-5-will-not-load-in-applications-also-targetting-net-3-5
http://arstechnica.com/civis/viewtopic.php?f=20&t=1112439
http://connect.microsoft.com/VisualStudio/feedback/details/510467/migrated-project-cant-compile-the-commandline-for-resgen-task-is-to-long
Any help is greatly appreciated. Thanks!
See these two blog posts to fix your problem:
http://traf-o-data.blogspot.com/2010/10/mystery-of-mscorlib.html
http://customerfx.com/pages/integrationblog/2010/11/08/working-with-crystal-reports-v11-5-and-visual-studio-2010-error-adding-references-to-crystaldecisions-dlls.aspx
58 Projects is a lot! One of the first things I would try is removing some of them from the solution. Knowing your going to get other errors about referencing the ones you took out, but if that error disappears/stays then you have a better idea of which one is your problem child.
Another approach may be to create a new VS2010 solution, then add the projects back one-by-one. 58 projects is going to cause you pain, I feel for you!