# Thursday, 15 November 2007
0.36 Release Plan

Ben asked about the 0.36 release yesterday. Here's the situation: There will be at least one more 0.36 release candidate that includes the new custom assembly class loader support and the fixes I've done since rc5. I'm currently waiting for some test results from the sponsor of the 0.36 release, to make sure that everything that needs to be fixed is fixed before release.

Thursday, 15 November 2007 08:12:29 (W. Europe Standard Time, UTC+01:00)  #    Comments [2]
# Tuesday, 13 November 2007
Development Snapshot Update

Three more fixes and a complete set of binaries this time.

Changes:

  • Fix to make sure that a ghost interface method call always goes thru the target reference wrapping path. (Calling java.lang.CharSequence methods through an interface that extends java.lang.CharSequence would generate incorrect code.)
  • Fixed ghost interface array casting to generate verifiable code.
  • Fixed FileChannelImpl to close the FileDescriptor after releasing the file locks.

Binaries available here: ikvmbin-0.37.2873.zip.

Update: Fixed the link.

Tuesday, 13 November 2007 08:19:28 (W. Europe Standard Time, UTC+01:00)  #    Comments [3]
# Friday, 02 November 2007
Development Snapshot Update

Two fixes. This time I'm only releasing an updated version of IKVM.Runtime.dll as that is all that changed.

Changes:

  • AppDomainAssemblyClassLoader now skips AssemblyBuilders. Previous version would cause problems if any dynamically generated assemblies were present in the AppDomain.
  • Fixed a bug in the DynamicMethod based reflection implementation that caused a NullPointerException when generating the setter for a final instance field for code that isn't compiled with -strictfinalfieldsemantics.

Update available here: ikvmbin-upd-0.37.2862.zip.

Friday, 02 November 2007 08:02:15 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Friday, 26 October 2007
Writing a Custom Assembly Class Loader

A new development snapshot. It's now possible to write your own custom assembly class loader. This is the recommended pattern:

class MyCustomClassLoader extends ClassLoader
{
  MyCustomClassLoader(cli.System.Reflection.Assembly asm)
  {
    super(new ikvm.runtime.AssemblyClassLoader(asm));
  }

  protected Class findClass(String name)
  {
    // TODO: forward call to other class loader or load class and call defineClass()
  }

  protected URL findResource(String name)
  {
    // TODO: forward call to other class loader or find resource somewhere
  }

  protected Enumeration findResources(String name)
  {
    // TODO: forward call to other class loader or find resources somewhere
  } 
}

If you delegate to other class loaders, you should be careful to avoid loops in the delegation path. If you want to change the resource loading delegation order, you can override getResource[s]() instead of findResource[s]() relatively safely, but if you want to change the delegation order for classes you need to be more careful, because you cannot replace any classes that are defined in the assembly.

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));
    // see below why calling addURL() is safer than passing it to the super constructor
    addURL(new java.net.URL("..."));
  }
}

Note that custom assembly class loader classes and their single argument Assembly constructor must be accessible from the assembly that they are applied to.

Delegation Magic

The ikvm.runtime.AssemblyClassLoader instance that is passed in as the parent class loader is a bit funny. It supports loading classes and resources from the assembly, but it effectively does this by magically delegating back to the custom class loader (without actually calling it, otherwise you'd get infinite recursion.) This means that classes from the assembly can be loaded via the parent class loader, but they report the custom class loader instance as their class loader.

Construction Magic

The custom assembly class loader is constructed when someone calls getClassLoader() on a class defined in that assembly for the first time, but what should getClassLoader() return while the custom class loader is being constructed? For consistencies sake, I've decided to apply some magic here and to make it return the object that is currently being constructed. This implies that you should call the base class constructor ASAP, because as long as you haven't done this the ClassLoader instance is in an unitialized state. After calling the base class constructor you can do additional work to configure your custom class loader, but you should take into account that while you are setting up your instance data, if you do anything that causes a class or resource to be loaded via your class loader, that your methods may run while initialization has not yet been completed. Note that this can only happen for the initiating thread. All other threads that call getClassLoader() will be blocked while the constructor is runnning. If the constructor throws an exception, the initiating call to getClassLoader() will see the exception, but all other calls will return the partially initialized class loader object.

Too Much Magic?

I certainly hope not, but I have to admit this is a scary feature. I recommend only writing your own custom assembly class loader if you really understand Java class loaders and there is no alternative.

Finally, please do send me feedback on this feature (even if it's a simple "I like it" or "It sucks"). I plan on backporting this to the 0.36 release, so it's important to get this right.

Changes:

  • More changes to keep up the pretense that an AssemblyClassLoader has already loaded all classes in the assembly.
  • Made AssemblyClassLoader public and moved it to ikvm.runtime package.
  • Allow non-public custom assembly class loaders (if they are defined in the same assembly).
  • Fixed ClassLoader.getSystemClassLoader() to return the custom assembly class loader for the main executable, if one is defined, even if the java.class.path or java.ext.dirs system property is set.
  • Restructured AssemblyClassLoader.GetProtectionDomain() to avoid calling any code while holding the lock.

Binaries available here: ikvmbin-0.37.2855.zip.

Friday, 26 October 2007 11:25:23 (W. Europe Daylight Time, UTC+02:00)  #    Comments [4]
# Monday, 22 October 2007
New Development Snapshot

I've made a bunch of changes to support custom assembly class loaders. This should finally solve some of the issues caused by the new class loader architecture. Eventually it will be possible to write your own assembly class loader (hence the name custom assembly class loaders), but currently only the two provided ones are supported: ikvm.runtime.AppDomainAssemblyClassLoader and ikvm.runtime.ClassPathAssemblyClassLoader.

AppDomainAssemblyClassLoader

This approximates the pre-0.32 behavior by searching all currently loaded assemblies (after looking in the assembly itself and the assemblies it references).

ClassPathAssemblyClassLoader

This class loader supports dynamically loading classes and resources from the CLASSPATH (or java.class.path system property). It too first searches the assembly itself and any assemblies it references. This class loader makes the most sense as a replacement for the assembly class loader of the main executable, that way it will also be the system class loader. Note that if multiple assemblies use this class loader, they each will have a separate class loader instance that loads different classes (even though they may be based on the same class files).

How to Use

There is a new ikvmc option to specify a custom assembly class loader:

ikvmc -classloader:ikvm.runtime.AppDomainAssemblyClassLoader example.jar

For non-Java code you can apply a custom attribute to your code:

using System;

[assembly: IKVM.Attributes.CustomAssemblyClassLoader(typeof(ikvm.runtime.ClassPathAssemblyClassLoader))]

class SimpleJavaRunner
{
  public static void Main(string[] args)
  {
    string[] newArgs = new string[args.Length - 1];
    Array.Copy(args, 1, newArgs, 0, newArgs.Length);
    java.lang.Class.forName(args[0])
      .getMethod("main", typeof(string[]))
      .invoke(null, new object[] { newArgs });
  }
}

You can also specify them in the app.config file, this overrides the above methods:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="ikvm-classloader:MyExampleAssembly" value="ikvm.runtime.AppDomainAssemblyClassLoader, IKVM.OpenJDK.ClassLibrary, Version=0.37.0.0, Culture=neutral, PublicKeyToken=null" />
  </appSettings>
</configuration>

Here the key is ikvm-classloader: followed by the simple name of the assembly. The value must be the assembly qualified type name of the custom assembly class loader type.

As always, feedback is appreciated.

Changes:

  • Implemented Custom Assembly Class Loaders.
  • Fixed URL.equals() for "ikvmres:" urls.
  • Fixed findResources() bug that caused resources in core assembly to show up twice if a .NET assembly explicitly referenced the core assembly.
  • Added check to prevent defineClass() on an assembly class loader from defining a class that already exists in the assembly.
  • Fixed Class.getModifiers() to mask out ACC_SUPER bit.

Binaries available here: ikvmbin-0.37.2851.zip.

Monday, 22 October 2007 15:22:38 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Monday, 15 October 2007
Mono Summit 2007

I'll be at the Mono Summit 2007.

Monday, 15 October 2007 11:59:24 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Friday, 12 October 2007
IKVM 0.36 rc5

Yet another release candidate and possibly not even the last one (more on that next week).

Changes:

  • Fixed reflection regression introduced in rc4.
  • Added workaround for .NET 3.5 beta breaking change.
  • Added support for another binary compatibility issue (public classes nested in non-public classes).
  • Added workaround for another .NET 2.0 x64 JIT bug.

Binaries available here: ikvmbin-0.36.0.4.zip.

Sources (+ binaries): ikvm-0.36.0.4.zip

External sources (haven't changed since rc1): classpath-0.95-stripped.zip, openjdk-b13-stripped.zip

Friday, 12 October 2007 18:28:39 (W. Europe Daylight Time, UTC+02:00)  #    Comments [3]
# Monday, 01 October 2007
IKVM 0.36 rc4

External forces inspired me (read: I was paid) to make another release candidate.

Reflection on .NET is very slow compared with Java and because IKVM reflection was built on top of .NET reflection, it too was very slow. I rewrote the lower levels of reflection to take advantage of DynamicMethod when running .NET 2.0. This allows the slow .NET reflection to be bypassed and optimized accessor methods to be generated dynamically. I also rewrote the part of serialization that uses reflection to get and set the field values to generate custom dynamic methods for the serialization process. Serialization is now up to 20x faster.

Unfortunately I had to disable the use of DynamicMethod when running on Mono, because testing revealed that Mono 1.2.5's implementation of DynamicMethod is still too buggy.

A remaining caveat wrt reflection performance is that you need to call setAccessible(true) to get the best performance when running on IKVM, because stack walking (which is needed to do the required access checks when you access a non-public member) is still very slow compared with Java.

Changes:

  • Improved serialization and reflection performance when running on .NET 2.0.

Binaries available here: ikvmbin-0.36.0.3.zip.

Sources (+ binaries): ikvm-0.36.0.3.zip

External sources (haven't changed since rc1): classpath-0.95-stripped.zip, openjdk-b13-stripped.zip

Monday, 01 October 2007 15:31:54 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Thursday, 20 September 2007
IKVM 0.36 rc3

This is probably the last release candiate before the official 0.36 release.

Changes:

  • Fixed non-blocking nio socket send of zero bytes to not return -1.
  • Fixed nio Selector.wakeup() race condition.
  • Added checks for code that uses reflection to call ClassLoader.defineClass() on the assembly class loader for ikvmc compiled classes to throw IllegalAccessError when the class tries to extend a non-public base class (instead of dying with a Critical Failure).
  • Fixed bug in the handling of Java annotations applied in .NET code (via the corresponding ikvmc generated attributes).
  • Significantly improved performance of Class.getModifiers().

Binaries available here: ikvmbin-0.36.0.2.zip.

Sources (+ binaries): ikvm-0.36.0.2.zip

External sources (haven't changed since rc1): classpath-0.95-stripped.zip, openjdk-b13-stripped.zip

Thursday, 20 September 2007 15:55:12 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Monday, 17 September 2007
Two Useful Tools for IKVM.NET

IKVMDoc

Brian Heineman wrote a doclet to convert Javadoc into .NET XML documentation that can be consumed by .NET tools like Visual Studio. This makes the type and member documentation available in the Visual Studio IntelliSense popups. Very nice! There's still room for improvement, especially in the area of converting broken html tags into well formed xml tags. The code is available cvs. I've used it to generate an xml documentation file for IKVM.OpenJDK.ClassLibrary.dll and that can be downloaded here.

In future IKVM releases I plan to include an ikvmc compiled version of IKVMDoc.

jar2ikvmc

Gena Donchyts wrote a handy tool that analyzes a bunch of jars and generates a script to ikvmc compile these jars in the right order and with the required (static) dependencies. The tool and documentation are available here.

Thanks

Thanks to Brian and Gena for providing these great tools!

Monday, 17 September 2007 08:18:25 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]