-
-
Notifications
You must be signed in to change notification settings - Fork 125
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #75 from NightOwl888/docs/ikvm-wiki
Added docs from SourceForge WIKI
- Loading branch information
Showing
18 changed files
with
1,217 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
# ClassLoader | ||
|
||
The class path or the usage of `ClassLoader`s is a little difficult because Java and .NET are not compatible. When there is an issue, it often results in a [ClassNotFoundException](class-not-found-exception.md). | ||
|
||
In Java you can set the class path with: | ||
|
||
- the environment variable CLASSPATH | ||
- use the -cp switch on command line | ||
- the property Class-Path in the MANIFEST.MF of a jar file. | ||
- Use a `URLClassLoader` or your own `ClassLoader` | ||
|
||
This is a little different in .NET which can produce class loading problems. The following is a list of strategies that can be used to solve class loading problems on .NET. | ||
|
||
- [Compile time solutions](#compile-time-solutions) | ||
- [One large assembly](#one-large-assembly) | ||
- [AppDomainAssemblyClassLoader](#appdomainassemblyclassloader) | ||
- [sharedclassloader](#sharedclassloader) | ||
- [ClassPathAssemblyClassLoader](#classpathassemblyclassloader) | ||
- [Runtime solutions](#runtime-solutions) | ||
- [BootClassPathAssemby](#bootclasspathassembly) | ||
- [Context class loader](#context-class-loader) | ||
- [URLClassLoader](#urlclassloader) | ||
- [Related blog entries](#related-blog-entries) | ||
|
||
## Compile time solutions | ||
|
||
### One large assembly | ||
|
||
The simplest solution is to compile all with [ikvmc](tools/ikvmc.md) in a single assembly. There is no class loading problem in this case. The disadvantages are: | ||
|
||
- a performance degree, you need to load all possible components. For example all supported JDBC driver if you only need one at one moment. | ||
- duplicate resources files are lost. Like in one jar also in one dll a single file can exist only once. If the resources identical it is no problem. But with service for dynamic loading of components it is fatal. For example a JDBC driver registers it self if it in the classpath. If you have multiple JDBC drivers then only one is registers. | ||
|
||
### AppDomainAssemblyClassLoader | ||
|
||
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: | ||
|
||
```console | ||
ikvmc -classloader:ikvm.runtime.AppDomainAssemblyClassLoader MyJar.jar | ||
``` | ||
|
||
### sharedclassloader | ||
|
||
If you compile multiple jar files to multiple assemblies then you can use the option sharedclassloader. | ||
|
||
```console | ||
ikvmc -sharedclassloader { first.jar } { second.jar } { third.jar } | ||
``` | ||
You can only share the classloader between the jar files that was create in one step. | ||
|
||
### ClassPathAssemblyClassLoader | ||
|
||
It first searches the assembly (and, again, the assembly directly referenced) and then the class path. | ||
|
||
```console | ||
ikvmc -classloader:ikvm.runtime.ClassPathAssemblyClassLoader MyJar.jar | ||
``` | ||
|
||
## Runtime solutions | ||
|
||
### BootClassPathAssembly | ||
|
||
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. | ||
|
||
```c# | ||
ikvm.runtime.Startup.addBootClassPathAssembly(Assembly.Load("YourDll")); | ||
``` | ||
The class ikvm.runtime.Startup is saved in IKVM.OpenJDK.Core.dll. | ||
|
||
### Context class loader | ||
|
||
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: | ||
|
||
```java | ||
Class.forName( "org.company.abc.DynamicLoadedClass", true, Thread.currentThread().getContextClassLoader() ); | ||
``` | ||
|
||
If you do 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 `BootClassPathAssembly` 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: | ||
|
||
```c# | ||
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. | ||
|
||
```c# | ||
java.lang.Class clazz = typeof(org.company.xyz.FirstClass); | ||
java.lang.Thread.currentThread().setContextClassLoader( clazz.getClassLoader() ); | ||
new org.company.xyz.FirstClass(); | ||
``` | ||
|
||
### URLClassLoader | ||
|
||
Of course, you can also reuse existing class loader classes. Here's an example with `URLClassLoader`: | ||
|
||
```java | ||
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("...")); | ||
} | ||
} | ||
``` | ||
|
||
## Related blog entries | ||
|
||
- [Class Loading Architecture](https://web.archive.org/web/20210518052001/https://weblog.ikvm.net/PermaLink.aspx?guid=4e0b7f7c-6f5d-42a3-a4d6-5d05a99c84ff) | ||
- [New Development Snapshot](https://web.archive.org/web/20080502034606/http://weblog.ikvm.net/PermaLink.aspx?guid=8a457a80-1e5f-4182-8f78-b2cd67845553) | ||
- [Writing a Custom Assembly Class Loader](https://web.archive.org/web/20210518035313/http://weblog.ikvm.net/PermaLink.aspx?guid=375f1ff8-912a-4458-9120-f0a8cfb23b68) | ||
|
||
## Related | ||
|
||
- [ClassNotFoundException](class-not-found-exception.md) | ||
- [Components](components.md) | ||
- [Convert a .jar file to a .dll](convert-a-jar-file-to-a-dll.md) | ||
- [ikvmc](tools/ikvmc.md) | ||
- [Tutorial](tutorial.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# ClassNotFoundException | ||
|
||
One of the most ask question in the IKVM mailing list is the java.lang.ClassNotFoundException like: | ||
|
||
```java | ||
Exception in thread "main" java.lang.ClassNotFoundException: com.xyz.Xyz | ||
at java.net.URLClassLoader$1.run(URLClassLoader.java:366) | ||
at java.net.URLClassLoader$1.run(URLClassLoader.java:355) | ||
at java.security.AccessController.doPrivileged(AccessController.java:279) | ||
at java.security.AccessController.doPrivileged(AccessController.java:520) | ||
at java.net.URLClassLoader.findClass(URLClassLoader.java:354) | ||
at java.lang.ClassLoader.loadClass(ClassLoader.java:450) | ||
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) | ||
at java.lang.ClassLoader.loadClass(ClassLoader.java:385) | ||
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:500) | ||
at IKVM.Internal.ClassLoaderWrapper.LoadClassImpl(Unknown Source) | ||
at IKVM.Internal.ClassLoaderWrapper.LoadClassByDottedNameFastImpl(Unknown Source) | ||
at IKVM.Internal.ClassLoaderWrapper.LoadClassByDottedName(Unknown Source) | ||
at IKVM.NativeCode.java.lang.Class.forName0(Unknown Source) | ||
at java.lang.Class.forName0(Native Method) | ||
at java.lang.Class.forName(Class.java:287) | ||
``` | ||
|
||
This occurs if you do a mistake at compile time. There can be the following causes: | ||
|
||
1. You forgot to compile a needed `.jar` file in an assembly. In this case you should have receive a IKVMC0105 error message from `ikvmc`. Add the missing `.jar` file to your `ikvmc` command line. | ||
2. The different `.dll`s have no references to the other. A simple solution can be to use a [sharedclassloader](class-loader.md#sharedclassloader). | ||
3. Analyze the `ikvmc` warnings to locate the name of the class which was not found. | ||
|
||
If this does not help then open a new issue on GitHub. Your issue should include: | ||
|
||
- The `ikvmc` command line(s). | ||
- The name of the `.jar` file which include the missing class. | ||
- The name of the `.jar` file which include the class which call `Class.forName`. This can you see in the line under `Class.forName`. | ||
- The warnings from your `ikvmc` call. | ||
|
||
## Related | ||
|
||
- [ClassLoader](class-loader.md) | ||
- [ikvmc Warnings](tools/ikvmc.md#warnings) | ||
- [Tutorial](tutorial.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# Components of IKVM | ||
|
||
## Tools | ||
|
||
- [ikvm](tools/ikvm.md) | ||
Starter executable, comparable to java.exe ("dynamic mode"). The Java application will start slow because all classes need to converted on the fly. | ||
|
||
- [ikvmc](tools/ikvmc.md) | ||
Static compiler. Used to compile Java classes and jars into a .NET assembly ("static mode"). There are different classloader options. | ||
|
||
- [ikvmstub](tools/ikvmstub.md) | ||
A tool that generates stub class files from a .NET assembly, so that Java code can be compiled against .NET code. IKVM understands the stubs and replaces the references to the stubs by references to the actual .NET types. | ||
|
||
- IKVM.Runtime.dll | ||
The VM runtime and all supporting code. It contains (among other things): | ||
|
||
- Byte Code JIT compiler/verifier: Just-in-time compiles Java Byte Code to CIL. | ||
- Object model remapping infrastructure: Makes System.Object, System.String and System.Exception appear to Java code as java.lang.Object, java.lang.String and java.lang.Throwable. | ||
- Managed .NET re-implementations of the native methods in Classpath. | ||
|
||
- IKVM.Java.dll | ||
This are a compiled version of the Java class libraries, plus some additional IKVM specific code. | ||
|
||
- ikvm-native.dll / libikvm-native.so | ||
Small unmanaged C library that is used by the JNI interface. This is an optional part, and on Windows it is only required when an application uses it's own native libraries. When running on Linux, this library is also used by the NIO memory mapped files implementation. This library has been designed not to require any changes between IKVM versions, so if you download or compile a new version of IKVM, you don't necessarily need to update this native library. | ||
|
||
- IKVM.AWT.WinForms.dll | ||
This are the AWT and Swing peers. This include the java.awt.Toolkit, fonts, images and more GUI stuff. | ||
|
||
## Related | ||
|
||
- [ClassLoader](class-loader.md) | ||
- [ikvm](tools/ikvm.md) | ||
- [ikvmc](tools/ikvmc.md) | ||
- [ikvmstub](tools/ikvmstub.md) | ||
- [User Guide](user-guide.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# Concepts | ||
|
||
IKVM converts the Java byte-code into .NET IL code (Intermediate Language). This means the result is a .NET application. There are 2 modes for this conversion. On the fly with [ikvm](tools/ikvm.md) and via a compiler with [ikvmc](tools/ikvmc.md). | ||
|
||
In both mode you convert byte-code and not the API. IKVM is not a cross-compiler with exceptions. This means you need a Java runtime API in .NET. This are all the dll's of IKVM. This are approximate 40MB overhead for your application. Depending of the used API some not used dll's can be removed if you are finish. This is not recommend. | ||
|
||
There are also 2 types of code developments. You can write your code in any Java VM like Java or Scala. Or you write your code in any .NET language like C# or VB#. In the follow we will only speech from Java and C# also if any other language of this platform is possible. | ||
|
||
- [Running on the fly](#running-on-the-fly) | ||
- [Running with compiler](#running-with-compiler) | ||
- [Developing in Java code](#developing-in-java-code) | ||
- [Developing in C# code](#developing-in-c-code) | ||
|
||
## Running on the fly | ||
|
||
In this case you need to develop in Java code (see below). You need only to replace the Oracle or OpenJDK runtime with the IKVM runtime. In some cases it can help to rename ikvm.exe to java.exe. This is how you should begin. This mode is most compatible to Java. | ||
|
||
The disadvantages is that this mode is very slow on start time. Every Java byte-code class need to converted to a IL class on every run. This is a large overhead for large projects. | ||
|
||
More details can you find in a completely [step by step example](run-a-jar-file-on-the-fly.md). | ||
|
||
## Running with compiler | ||
|
||
In this mode you compile one or more jar files to a dll or exe file. It is recommended to compile every jar file to a separate dll or exe file. This start many faster than the on the fly mode. | ||
|
||
The disadvantage is a switch from the Java class loading concept to the .NET class loading. Several strategies for dealing with the gap between .NET and Java are discussed in the [ClassLoader](class-loader.md) topic. | ||
|
||
## Developing in Java code | ||
|
||
To access .NET libraries in your Java code you create a stub file from a .NET library. This can you do with [ikvmstub](tools/ikvmstub.md). A IKVM stub file is a *.jar file, a Java library. It contains only definitions of classes and methods, but no code. If you run a stub file with the Oracle Java VM or OpenJDK you will receive an error. | ||
|
||
The .NET classes start with the package CLI. | ||
|
||
Some .NET constructs require a specific syntax in Java. This are list in [Using .NET with Java](using-dotnet-with-java.md). | ||
|
||
## Developing in C# code | ||
|
||
This is only possible with compiler mode. You compile you jar files to a dll or exe. Add it as reference to your IDE. You can use every class and method like from any other .NET class library. | ||
|
||
Some Java constructs require a specific syntax in .NET. This is exemplified in [Using Java with .NET](using-java-with-dotnet.md). | ||
|
||
See the [step by step example](convert-a-jar-file-to-a-dll.md) for details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# Convert a .jar file to a Class Library (.dll) | ||
|
||
This is the recommended solution if you want access a existing Java library from your .NET application. Depending on programming errors in the Java library this can be difficult. | ||
|
||
First you need to [download](https://github.com/ikvm-revived/ikvm/releases) and [install](installation.md) IKVM. | ||
|
||
## Java sample code | ||
|
||
First we create a hello world sample in Java and create a .jar file. The sample Java code of `HelloWorld.java` is very simple: | ||
|
||
```java | ||
package hello; | ||
|
||
public class HelloWorld { | ||
private String name; | ||
|
||
public HelloWorld() { | ||
this.name = "World"; | ||
} | ||
|
||
public HelloWorld(String name) { | ||
this.name = name; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "Hello " + name; | ||
} | ||
} | ||
``` | ||
|
||
You can save it as `HelloWorld.java` and compile it with the javac command line: | ||
|
||
```console | ||
javac HelloWorld.java | ||
``` | ||
|
||
This should create a file `HelloWorld.class`. With any zip program you can create a .jar file `HelloWorld.jar`. A jar file is only a zip file. The .jar file must include the file `HelloWorld.class` in the folder `hello`. This is the package name of the class. In Java package names are identical to folder names. | ||
|
||
## Create a dll | ||
|
||
The .jar file compile you with [ikvmc](tools/ikvmc.md). This can you do with the follow command line: | ||
|
||
```console | ||
ikvmc -target:library HelloWorld.jar | ||
``` | ||
|
||
If you want compile more as one .jar file then follow syntax is recommended: | ||
|
||
```console | ||
ikvmc -target:library -sharedclassloader { first.jar } { second.jar } { third.jar } | ||
``` | ||
|
||
Why this is recommend can you read in the [ClassLoader](class-loader.md) topic. This should produce the follow output: | ||
|
||
```console | ||
IKVM.NET Compiler version x.x.xxxx.x | ||
Copyright © 2022 Jeroen Frijters, Windward Studios, Jerome Haltom, Shad Storhaug | ||
|
||
note IKVMC0002: Output file is "HelloWorld.dll" | ||
``` | ||
|
||
## C# Sample Code | ||
|
||
In your C# IDE you create a new project. Add a reference to `System` and `HelloWorld.dll`. Add a package reference on [IKVM](https://www.nuget.org/packages/IKVM). In your program file you can copy the follow C# sample code: | ||
|
||
```c# | ||
using System; | ||
using System.Reflection; | ||
|
||
namespace JavaLibrary | ||
{ | ||
class Program | ||
{ | ||
static void Main(string[] args) | ||
{ | ||
//Add references to all jar files that you use not directly | ||
//ikvm.runtime.Startup.addBootClassPathAssemby(Assembly.Load("second")); | ||
//ikvm.runtime.Startup.addBootClassPathAssemby(Assembly.Load("third")); | ||
// set a context classloader, this is not needed for the HelloWorld sample | ||
// but solv problems with some buggy Java libraries | ||
java.lang.Class clazz = typeof(hello.HelloWorld); | ||
java.lang.Thread.currentThread().setContextClassLoader(clazz.getClassLoader()); | ||
|
||
object obj = new hello.HelloWorld(); | ||
Console.WriteLine(obj); | ||
obj = new hello.HelloWorld("Java"); | ||
Console.WriteLine(obj); | ||
} | ||
} | ||
} | ||
``` | ||
|
||
If you run this program then it produce the follow output: | ||
|
||
```console | ||
Hello World | ||
Hello Java | ||
``` | ||
|
||
## Related | ||
|
||
- [ClassLoader](class-loader.md) | ||
- [ikvmc](tools/ikvmc.md) | ||
- [Installation](installation.md) |
Oops, something went wrong.