The class path or the usage of ClassLoaders is a little difficult because Java and .NET are not compatible. This results mostly in a [ClassNotFoundException].
In Java you can set the class path with:
This is a little different in .NET which can produce class loading problems.
The simplest solution is to compile all with [Ikvmc] in a single assembly. There is no class loading problem in this case. The disadvantages are:
This classloader loads from all assemblies that are currently loaded in your application (AppDomain in .NET lingo). So if a referenced assembly has not yet been loaded, it will not be searched at least not by the "AppDomain" part of the class loader, the default assembly class loader mechanism will still load referenced assemblies that are directly referenced by your assembly.
You can set it with the follow command line:
ikvmc -classloader:ikvm.runtime.AppDomainAssemblyClassLoader MyJar.jar
If you compile multiple jar files to multiple assemblies then you can use the option sharedclassloader.
ikvmc -sharedclassloader { first.jar } { second.jar } { third.jar }
You can only share the classloader between the jar files that was create in one step.
It first searches the assembly (and, again, the assembly directly referenced) and then the class path.
ikvmc -classloader:ikvm.runtime.ClassPathAssemblyClassLoader MyJar.jar
If you have a Visual Studio project then it does not help if you add the needed dlls as reference. You need also to use it. But an internal, dynamic use with Class.forName(x) can not detect as usage from Visual Studio. If you have a main program written in .NET then you can register your dll with the follow program line at startup of your program.
ikvm.runtime.Startup.addBootClassPathAssemby(Assembly.Load("YourDll"));
The class ikvm.runtime.Startup is saved in IKVM.OpenJDK.Core.dll.
If you use one of the 3 class loaders for multiple DLL's then this has an effect to the default class loader. But Java know also the concept of the context class loader per thread. The standard class loader use the hierarchical class loader first and then the context class loader.
There are some bad design Java library which only use the context class loader. This look like:
Class.forName( "org.company.abc.DynamicLoadedClass", true, Thread.currentThread().getContextClassLoader() );
If you does not set the context class loader then it point to your main assembly and all assembly that are referenced from the compiler. Typical this means you can load all classes from your main assembly, the BootClassPathAssemby and from the first Java dll which you call directly.
You can add references to all DLL's in your main assembly with lines like:
GC.KeepAlive(typeof(org.company.abc.DynamicLoadedClass));
This can be difficult if you have a large count of DLLs. Another solution is to set the context class loader to the same as the default class loader before you load the first class.
java.lang.Class clazz = typeof(org.company.xyz.FirstClass); java.lang.Thread.currentThread().setContextClassLoader( clazz.getClassLoader() ); new org.company.xyz.FirstClass();
Of course, you can also reuse existing class loader classes. Here's an example with URLClassLoader:
class MyCustomClassLoader extends java.net.URLClassLoader { MyCustomClassLoader(cli.System.Reflection.Assembly asm) { super(new java.net.URL[0], new ikvm.runtime.AssemblyClassLoader(asm)); // explicitly calling addURL() is safer than passing it to the super constructor, // because this class loader instance may be used during the URL construction. addURL(new java.net.URL("...")); } }
Wiki: ClassNotFoundException
Wiki: Components
Wiki: Convert_a_jar_file_to_a_dll_and_use_it_as_library
Wiki: FAQ
Wiki: Ikvmc
Wiki: Tutorial