# Monday, 21 August 2006
New Snapshot

I fixed an ikvmstub regression introduced in the previous snapshot and fixed AssemblyClassLoader.getPackage[s]. I did some class file fuzzing and fixed most differences between JDK 1.5 and IKVM (most are trivial and only fixed to reduce the noise in the fuzz differences, but I also found a couple of real bugs).

Other changes:

  • Fixed runtime class loading to handle class loaders that return null or the wrong class.
  • Fixed Constructor to prevent instantiating Enum objects.
  • Fixed ikvmc not to stop with error when encountering invalid .class files. Also, when it encounters a .class file in a zip or jar that does not start with the Java class magic value it will include the .class file as a resource.
  • Improved ikvmc warnings about invalid classes to include the filename.
  • Fixed class file parser to correctly check the class file minor version.
  • Fixed field and method name validation in class file parser.
  • Fixed class file parser to check length of Deprecated attribute.
  • Fixed class file parser to check length of InnerClasses attribute when class file version is >= 49.
  • Fixed class file parser to always validate NameAndType constant pool entries.
  • Fixed class file parser to check for maximum method size of 65535 instead of 65536.
  • Fixed class file parser to check some properties of exception handler tables (instead of doing that at verification time).
  • Fixed reflection (Class.getDeclaredMethods) to throw ClassFormatError or VerifyError.
  • Fixed handling of inner class modifier flags to always use the flags from the inner classes attribute, except for the accessibility flags.
  • Fixed verifier/compiler to emit methods that throw ClassFormatError, instead of only VerifyError.
  • Fixed verifier to disallow exception handlers starting at bytecode offset zero.
  • Fixed verifier to better check invokeinterface.

Source is in cvs. Binaries: ikvmbin-0.31.2424.zip

Monday, 21 August 2006 07:24:22 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Friday, 18 August 2006
Breaking Changes

Now that 0.30 has been released, it's time to talk about the next version. While 0.30 was baking, I've made some significant changes. People sometimes ask me why the version number is so low, part of the reason is that I anticipate that I'll need to make breaking changes a couple more times.

Moved Runtime API to IKVM.GNU.Classpath.dll

To make the runtime API easier to use and to allow (potential) future changes that remove the need for IKVM.Runtime.dll to discover IKVM.GNU.Classpath.dll, I moved the public API of the runtime into IKVM.GNU.Classpath.dll. Now, IKVM.Runtime.dll still exposes a bunch of public types, but you should not use any of these, they are "undocumented" and only for use by ikvmc generated code and IKVM.GNU.Classpath.dll. They will also change in future versions.

Revisiting the ClassLoader per Assembly Idea

Over the past couple of years I've slowly come around on my initial decision to have all classes in assemblies appear to be loaded by the boot class loader. My initial reluctance was mostly due to the fact that using a ClassLoader per assembly would require violating the ClassLoader delegation model, but the success of OSGi (which does the same) demonstrates that this isn't such a big deal.

Here are some of the advantages:

  • Each assembly will be its own namespace, meaning that things like Class.forName() and Class.getResource() will be able to search the calling assembly first, so you won't get into class or resource name conflicts as easily.
  • It removes the need for the hack that returns the system class loader, instead of null, for statically compiled classes.
  • It allows for many operations to be more efficient.
  • It removes the need for pre-loading assemblies to make Class.forName() work, because the assembly class loader will be able to search all referenced assemblies (i.e. ikvmc's -reference option will be honored by the assembly class loader).
  • You will be able to take full advantage of .NET assembly namespace separation (i.e. multiple versions of a jar can be compiled and used in the same AppDomain, by different pieces of code).
  • It allows for a more natural integration of ReflectionOnly support (when running a .NET 2.0 build of ikvmc or ikvmstub).

I made a new snapshot that you can play around with to evaluate how the change will impact you. Please let me know, now's the time to convince me to change some of the details ;-)

Here's a full list of changes in this snapshot:

  • Changed class loader architecture to represent each .NET assembly with its own class loader.
  • Changed system class loader to the application entry assembly class loader (except if the java.class.path system property is explicitly set, then you get a URL class loader that loads from the specified class path).
  • Ported stub class generator from C# to Java and incorporated it into IKVM.GNU.Classpath.dll.
  • Hooked up assembly class loader resource loading with stub generator, to support loading .class stub files for .NET and statically compiled classes.
  • Changed ikvmstub to create stub classes by simply loading them as resources.
  • Removed IKVM.Runtime.Util methods that existed for ikvmstub.
  • Fixed runtime/ikvmc to no longer depend on the CLR interning string literals.
  • Runtime no longer locks the class loader instance before calling loadClass.
  • Removed old mono bug work arounds from jni code.
  • Class.getProtectionDomain() now returns a more meaningful ProtectionDomain (including a CodeSource) for statically compiled Java code and .NET assemblies.
  • Moved VMSystem.setIn/setOut/setErr implementation from C# to Java.
  • Changed the way final instance fields are handled (added a private setter method to the property) to remove the need for the runtime to correlate the field with the property.
  • Fixed final field property accessor generator to make sure that the generated method name doesn't clash with other methods.
  • Moved IKVM.Runtime public API to IKVM.GNU.Classpath (and renamed to namespace and method names to follow Java naming convention).
  • Set system property to disable usage of Graphics 2D by Swing implementation.
  • Added java.vendor.url.bug, java.runtime.name and java.runtime.version system properties.

Source is in cvs. Binaries can be downloaded here: ikvmbin-0.31.2421.zip

Friday, 18 August 2006 11:09:00 (W. Europe Daylight Time, UTC+02:00)  #    Comments [5]
IKVM 0.30 Released

I released 0.30 (same bits as last week's rc1) to SourceForge.

Friday, 18 August 2006 10:02:31 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Thursday, 10 August 2006
IKVM 0.30 rc1

Here's the release candidate. Updated japi results are available here.

Changes since previous snapshot:

  • Integrated GNU Classpath 0.92.
  • Fixed ikvmc to handle constructorless classes correctly.
  • Fixed a couple of FileChannelImpl bugs.

Files are available here: ikvm-0.30.0.0.zip (sources + binaries), ikvmbin-0.30.0.0.zip (binaries), ikvmbin-generics-0.30.0.0.zip (binaries built from generics branch)

Thursday, 10 August 2006 10:38:07 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Thursday, 03 August 2006
New Snapshot

I'm preparing for the 0.30 release and this time I decided to do things a little more structured, so I made a branch in cvs: v0_30. I checked out the code into a clean directory changed allsources.lst and classpath.build to point to a clean check out of the GNU Classpath 0.92 release branch (Note that 0.92 has not yet been released) and ran the build script.

The resulting binaries are available here. Note that even though the directory inside the zip is ikvm-0.30.0.0, this is not yet 0.30, but instead should be considered a development snapshot and the binaries are unsigned and have version 0.29.*.

Please test this version and report any bugs, now's the time to get them fixed before 0.30 is released!

Here's what's new:

  • Integrated GNU Classpath 0.92-pre
  • Implemented java.util.concurrent.atomic.AtomicInteger, AtomicIntegerArray, AtomicReference, AtomicReferenceArray, java.util.concurrent.locks.LockSupport and the sun.misc.Unsafe and sun.reflect.Reflection classes required by java.util.concurrent.
  • Added support for Thread parking (as required by j.u.c.l.LockSupport) to VMThread.
  • Added support for ldind.ref, stind.i2, stind.i4, stind.ref and ldelema CIL instruction to remapper.
  • Fixed volatile long/double access to be atomic.
  • Implemented VM specific part of RuntimeMXBean.
  • Implemented VMNetworkInterface using System.Management (via reflection to make sure the code continues to "work" on Mono which doesn't have a System.Management implementation) based on code submitted by Rich Naylor.
  • Implemented DatagramSocket multicast join/leave [implemented by Rich Naylor]
  • Added exception handler to app.config settings reading to ignore exceptions when app.config is invalid.
  • Added support to ikvmstub to generate annotations for custom attributes (but support is limited to a few simple custom attribute signatures currently).
  • Moved assembly attributes from map.xml to AssemblyInfo.java
  • Moved ThreadStatic and DllImport attributes from map.xml to source.
  • Added support for applying assembly attributes (by way of the "assembly" placeholder class).
  • Fixed IsSideEffectFreeStaticInitializer to handle unused class literals and invalid class files.
  • Removed -Xbootclasspath support (it wasn't compatible with Sun and the implementation was very hacky).
  • Cleaned up ikvmstub class loading.
  • Fixed ReflectionOnly (when compiling for WHIDBEY target) bug when handling generic byref method parameters.
  • Fixed DynamicClassLoader.CreateModuleBuilder() to have it return the ikvmc target assembly instead of creating a new assembly.
  • Centralized array type construction.
  • Fixed cli.System.Void.class literal to yield cli.System.Void instead of void type (this also fixes ikvmstub to generate cli.System.Void instead of void when processing mscorlib).
  • Restructured class loading to remove DynamicClassLoader subclass and use delegation instead.
  • Fixed Socket and DatagramSocket to ignore timeout on write operations (reported by David Pirkle).
  • Fixed Socket and DatagramSocket to throw UnknownHostException when dealing with an unresolved SocketAddress.
  • Fixed VMFile.mkdir not to throw exception when trying to create an invalid directory name.
  • Fixed ArrayIndexOutOfBoundsException when trying to load class named "[[".
  • Fixed VMStackWalker.getClassContext() to skip one less frame [this fix makes Eclipse 3.2 start up].
  • Added a hack to prevent the x64 JIT from doing tail call optimizations.
  • Changed IKVM.GNU.Classpath.dll build script to use classpath.security file from GNU Classpath instead of ikvm specific version.
  • Much improved ReflectionOnly support (WHIDBEY target only).
  • Added a CompilationRelaxations assembly attribute to fix a bug that occurred when IKVM.Runtime.dll or ikvmc.exe were NGENed. The code relies on string literals being interned by the CLR, but starting with .NET 2.0 the C# compiler by default annotates the assemblies it generates with the CompilationRelaxations(CompilationRelaxations.NoStringInterning) attribute.
  • Relaxed class name restrictions for 1.5 class files.
  • Added support for Java classes with a Finalize() method (there was a know bug that the generated Finalize stub that calls the real finalize() method would conflict with a user defined Finalize() method).
  • Removed IkvmStubMode hack.
  • Changed naming and loading of CLR generic types.
  • Implemented the remaining 1.5 methods in java.lang.Class.
  • Added consistency checks to Class.getDeclaringClass() and Class.getDeclaredClasses().
  • Simplified loading of "manufactured" nested classes (i.e. the nested Method interface in delegates and the Annotation annotation in attributes).
  • Changed generic type instantiations to have a custom class loader that delegates to the class loaders that were used to create the type (at least when there are no type name clashes).
  • Cleaned up warning generation in ikvmc and added -nowarn option to suppress specific warnings.
  • Fixed volatile read/write on WHIDBEY target build of ikvmc.
  • Made array type construction more lazy. Constructing large dimensional array types is now much faster.
  • Changed ClassLoader.findLoadedClass() to be compatible with 1.5 instead of 1.4 (i.e. it no longer creates new array types).
  • Fixed compiler to mark methods that use getstatic/putstatic on fields in another class as not inlineable (because the instructions are effectively a method call when they trigger the static initializer).
  • Fixed compiler to mark methods that use dynamic getstatic/putstatic/getfield/putfield instructions as not inlineable.
  • Improved optimization in compiler that omits line number table from methods that cannot throw exceptions. It now understands that getfield/putfield on the this reference and getstatic/putstatic on the current class cannot throw.
  • Fixed a bug in exception handling that could cause a TypeInitializationException to turn into a ClassCastException.
  • Added cause exception to NoClassDefFoundError that gets thrown when a type that failed its static initializer is accessed again.

Thursday, 03 August 2006 18:31:36 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Tuesday, 01 August 2006
.NET Generic Types

Recently I changed the way .NET generic types are handled by IKVM. The previous scheme was based on a naive mangling of the .NET Type.FullName property, but that turned out to be problematic for various reasons. The first obvious reason was that type names often were way too long for comfort. For example:

Type t = typeof(System.Collections.Generic.List<string>);
Console.WriteLine(t.FullName);
Console.WriteLine(((java.lang.Class)t).getName());

With IKVM 0.28 this prints out:

System.Collections.Generic.List`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
cli.System.Collections.Generic.List$$00601$$005B$$005B System$$002EString$$002C$$0020mscorlib$$002C$$0020 Version$$003D2$$002E0$$002E0$$002E0$$002C$$0020 Culture$$003Dneutral$$002C$$0020 PublicKeyToken$$003Db77a5c561934e089$$005D$$005D


(I manually inserted some spaces to make the HTML wrap.)

This obviously isn't very practical, but there is also a deeper problem. This literal translation of the name misses the fact that class loading in .NET is fundamentally different from class loading in Java. Which means that it is easy to go from Type to class name, but given a class name it is much harder to construct the corresponding type, especially if on or more of the type parameters are Java types (or remapped types).

In the next release the class name will be:

cli.System.Collections.Generic.List$$00601_$$$_Ljava__lang__String_$$$$_

Not only more readable, but it also correctly reflects the fact that System.String is known as java.lang.String on the Java side.

I also changed the way these names are resolved to be more inline with the way Java works. The name is now parsed by the class loader that first tries to load the class which then in turn loads the component classes and constructs the generic type from that. This means that the following code will now work (if you can somehow convince your Java compiler to compile it):

import cli.System.Collections.Generic.*;

class Test
{
  public static void main(String[] args)
  {
    List$$00601_$$$_LTest_$$$$_ list = new List$$00601_$$$_LTest_$$$$_();
    list.Add(new Test());
  }
}


With the previous scheme there was no way to refer to the Test class in the generic class name, but now the correct class loader is used so you can refer to Java classes as well. That leaves only one question, what does list.getClass().getClassLoader() return? Well, for the time being I've decided to automatically construct a class loader that delegates to the defining class loaders of the classes used to construct the generic type, this ensures (as long as no types with the same names are used) that all types used in the definition of the generic type instance can be loaded by its class loader. It isn't actually clear to me that this is required, but at least for the time being it is, because some of the reflection code relies on this fact.

Finally, as a reminder, all this stuff is still experimental and, frankly, not intended to be practical. The main reason this support exists is to make the life of reflection/ikvmstub easier, otherwise the runtime would have to have all sorts of complicated support to deal with field types and method parameter/return types that take generic type instantiations.

Tuesday, 01 August 2006 15:11:32 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]