# Wednesday, 13 June 2007
New Hybrid Snapshot

A new snapshot. I integrated all classes in the java.lang package (but not the sub-packages) and this means I have now resolved most VM/Library initialization issues that I was a bit worried about before embarking on this. I had to include one new hackish (or AOP if you will) feature in map.xml: The ability to replace method invocations with arbitrary CIL code sequences. This was in particular necessary to "comment out" the loadLibrary("zip") call in System.initializeSystemClass(). Here's what that looks like in map.xml:

<class name="java.lang.System">
  <method name="initializeSystemClass" sig="()V">
    <replace-method-call class="java.lang.System" name="loadLibrary" sig="(Ljava.lang.String;)V">
        <pop />

This simply means that all System.loadLibrary() invocations in System.initializeClass() will be replaced with a pop instruction (to discard the string argument).


  • OpenJDK: Integrated java.lang package..
  • OpenJDK: Integrated java.util.regex package.
  • OpenJDK: Integrated java.text.Normalizer and support classes.
  • OpenJDK: New StringHelper.java based on OpenJDK's String.java.
  • OpenJDK: Implemented using the entry assembly's class loader as system class loader.
  • OpenJDK: Replaced zip library loading hack with "replace-method-call" hack.
  • OpenJDK: Implemented the hooks to set the system class loader to the entry assembly's class loader if java.class.path and java.ext.dirs properties aren't set.
  • OpenJDK: Various fixes.
  • Added leave CIL opcode support to remapper.
  • Added support for replacing constructor and static initializer method bodies in map.xml.
  • Added support for locally (i.e. per method) replacing method calls in map.xml.
  • Added optimization to ikvmc for large string literals that are only used to call .toCharArray() on.

Binaries available here: ikvmbin-hybrid-0.35.2720.zip.

Wednesday, 13 June 2007 08:35:28 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Tuesday, 12 June 2007
Array Initialization

One of the many limitations of the Java class file format is that it doesn't support an efficient way of initializing an array. Take the following class for example:

class Foo
  private static final int[] values = { 1, 2, 3, 4 };

This looks harmless enough, but it is compiled almost exactly the same as this:

class Foo
  private static final int[] values;

    int[] temp = new int[4];
    temp[0] = 1;
    temp[1] = 2;
    temp[2] = 3;
    temp[3] = 4;
    values = temp;

If you have an array with a few thousand entries, this is starting to look pretty inefficient. Here's how C# compiles the equivalent code (but with an array with more elements, for small arrays the C# compiler does the same as the javac):

using System.Runtime.CompilerServices;

  private static readonly int[] values;

  static Foo()
    int[] temp = new int[128];
    RuntimeHelpers.InitializeArray(temp, LDTOKEN($$field-0))
    values = temp;

This is pseudo C#, because there's no C# language construct that allows you to directly load a field's RuntimeFieldHandle as the ldtoken CIL instruction does. What happens here is that the C# compiler emits a global read-only data field and then uses RuntimeHelpers.InitializeArray() to copy this field into the array. If you're on a little endian machine, this is simply a memcpy (after checking that the sizes match).

On occasion I've toyed with the idea of making ikvmc recognize array initialization sequences and then converting them into this more efficient form. The reason that I never got around to it is that many people know that array initialization is inefficient and use a workaround: String literals.

Here's a fragment from OpenJDK's java.lang.CharacterData00 class:

static final char X[] = (

I've omitted most of the data, but the string has 2048 characters (and it's not the only one in this class). String literals can be efficiently stored in the class file format, so this is more efficient than explicitly initializing the array elements.

However, on IKVM there's a downside to this approach. Java requires that all string literals are interned and on .NET the string intern table keeps strong references to the interned strings (the Sun JVM uses weak references to keep track of interned strings). So that means that the 2048 character string above that is only used once will stay in memory for the entire lifetime of the application.

Fortunately, this particular scenario is easily detected in the bytecode compiler and can be optimized to use RuntimeHelper.InitializerArray().

Unfortunately, it turns out that the Reflection.Emit API that takes care of creating these read-only global data fields is a little too helpful and hence broken. What I didn't mention earlier is that these read-only global data fields need to have a type and that type has to be an explicit layout value type of the right size. ModuleBuilder.DefineInitializedData() automatically defines this type, but instead of making it private it creates a public type.

The type created by ModuleBuilder.DefineInitializedData() is named $ArrayType$<n> where <n> is the size of the value in bytes. The size is encoded in the type name to make it easy to reuse the same type for other fields that have the same size. It turns out we can abuse this knowledge to work around the limitations of ModuleBuilder.DefineInitializedData() by pre-creating the value type with the right name. Now we can have full control over the properties of the generated type (as long as it's compatible with the requirements of the read-only global field, of course).

Final note: While writing this blog entry I found that Mono's implementation of RuntimeHelpers.InitializeArray() leaves something to be desired.

Tuesday, 12 June 2007 08:45:48 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Monday, 04 June 2007
OpenJDK Library/VM Integration

In Merging the First OpenJDK Code and Another x64 CLR Bug I briefly mentioned the three different approaches that are available for integrating the OpenJDK classes with IKVM:

  1. Use existing native interface
  2. Use map.xml tricks
  3. Change the code (i.e. fork a specific source file)

This triggered a couple of questions in the comments.

Morten asked:

about your work of [i]ntegrating the whole of OpenJDK and [y]our 3 options. Could you provide more details? From what you write, it sounds like using aspectj to inject annotations could be useful. Codegeneration might also be useful?

Yes, that's essentially what option 2 is. The map.xml infrastructure allows me to add methods and fields to existing classes, or allows me to replace method bodies.

Albert Strasheim asked:

It's too bad that the Sun and Classpath code aren't compatible down to the native methods called by the pure Java code.

As Andrew pointed out, it would not have been possible or practical to reverse engineer the Sun native interface. Besides that, the Sun and GNU Classpath libraries have very different goals, so it actually makes a lot of sense for the interfaces to differ.

I figured that you'd go the "native methods in C#" route, so I'd be interested to know why you think that the "IKVM specific modifications" route is cleaner and more efficient (efficient in terms of performance or time to implement?).

It would seem that implementing the native methods in C# would be the best solution, but that's not always the case. Hopefully that will become clear below.


Let's look at some examples and the downsides and cost associated with each of the three options:

1. Use existing native interface

In terms of long term development cost, this is easily the best option. Once you understand the ikvmc native method mapping that is used by the class library, it is very easy to find to corresponding native method. Sun is not very likely to change the native method semantics without also modifying the method name or signature. When a new native method is added, the build process will fail due to the fact that the new native method isn't implemented (and hence generates an unverifiable JNI method stub).

In terms of runtime performance, this method can be very efficient, but only if the method parameters contains all the required data to work on, or if the data can be easily obtained in another efficient way. This is often not the case, because many of the Sun native methods use JNI reflection to access private fields in the object. Here are two real world examples, one where the native methods works really well and another one where it's not as efficient as I'd like:

namespace IKVM.NativeCode.java.lang.reflect
  public sealed class Array
    public static bool getBoolean(object arrayObj, int index)
      if (arrayObj == null)
        throw new jlNullPointerException();
      bool[] arr = arrayObj as bool[];
      if (arr != null)
        if (index < 0 || index >= arr.Length)
          throw new jlArrayIndexOutOfBoundsException();
        return arr[index];
      throw new jlIllegalArgumentException("argument type mismatch");

Clearly this is very efficient (and it makes you wonder why it's a native method at all). Here's one that's less efficient:

namespace IKVM.NativeCode.java.lang
  public sealed class Class
    public static bool isInterface(object thisClass)
      return TypeWrapper.FromClass(thisClass).IsInterface;

The thisClass parameter is a reference to the java.lang.Class object, but the VM wants to use its internal representation of a class (TypeWrapper), so here I need to use TypeWrapper.FromClass() to get the corresponding TypeWrapper object. Currently that's implemented by using reflection to access a private field in java.lang.Class (that was added through map.xml).

To contrast, here's the equivalent method for use with the GNU Classpath library:

namespace IKVM.NativeCode.java.lang
  public sealed class VMClass
    public static bool IsInterface(object wrapper)
      return ((TypeWrapper)wrapper).IsInterface;

Here only a downcast is required, because Class.isInterface() calls VMClass.isInterface(), which reads the vmdata field from Class and passes that to the native IsInterface method.

2. Use map.xml tricks

This is very powerful, but also much more expensive because it is much less obvious what's going on. In the case of a native method that is implemented, if you can't find it in the C# code, you'll probably eventually find it in map.xml, but when replacing an existing method it's very easy to miss the fact that the method is replaced. I've used method replacement in java.lang.ClassLoader to make bootstrap resource loading work. ClassLoader has two private methods getBootstrapResource() and getBootstrapResources() that are used to load resources from the boot class path. These methods are implemented by parsing the sun.boot.class.path system property and then using internal classes to load from these jars or directories. Obviously that won't do for IKVM, because the boot classes and resources are contained in the core library .NET assembly (currently named IKVM.Hybrid.GNU.Classpath.OpenJDK.dll). So I've had to replace these two methods:

<class name="java.lang.ClassLoader">
  <field name="wrapper" sig="Ljava.lang.Object;" modifiers="private" />
  <method name="getBootstrapResource" sig="(Ljava.lang.String;)Ljava.net.URL;">
      <ldarg_0 />
      <call class="java.lang.LangHelper"
            name="getBootstrapResource" sig="(Ljava.lang.String;)Ljava.net.URL;" />
      <ret />
  <method name="getBootstrapResources" sig="(Ljava.lang.String;)Ljava.util.Enumeration;">
      <ldarg_0 />
      <call class="java.lang.LangHelper"
            name="getBootstrapResources" sig="(Ljava.lang.String;)Ljava.util.Enumeration;" />
      <ret />

These method bodies simply call the real implementations in LangHelper, because it's obviously easier to implement them in Java than in CIL.

3. Change the code (i.e. fork a specific source file)

In some cases, the changes required are so substantial that the map.xml trickery doesn't work or isn't practical. For an example of that we need to look at how reflection is implemented in OpenJDK.

Here's a fragment of java.lang.reflect.Method (not the actual code, but it gets the idea across):

package java.lang.reflect;

public final class Method
  private static final ReflectionFactory reflectionFactory = (ReflectionFactory)
    AccessController.doPrivileged(new sun.reflect.ReflectionFactory.GetReflectionFactoryAction());
  private MethodAccessor methodAccessor;

  public Object invoke(Object obj, Object... args)
    // ... access checks omitted ...
    if (methodAccessor == null)
      methodAccessor = reflectionFactory.newMethodAccessor(this);
    return methodAccessor.invoke(obj, args);

So the actual method invocation is delegated to an object that implements the MethodAccessor interface. By default Sun's ReflectionFactory returns an object that counts the number of invocations and delegates to another MethodAccessor object that uses JNI to use the VM reflection infrastructure, if the invocation counter crosses a certain value the inner object is replaced by an instance of a dynamically generated class that contains custom generated byte codes to efficiently call the target method (and this generated bytecode is not verifiable, so it won't work as-is on IKVM). In this case I've decided to fork ReflectionFactory and implement my own version that simply returns MethodAccessor instances that reuse the IKVM reflection infrastructure.

The cost of forking a source file should be obvious. When improvements are made to the original, you don't automatically inherit these. In this particular case ReflectionFactory is a fairly small and simple class (all of the complexity is in the classes it calls), so the risk seems low.

Structural Issues

Besides the issues already pointed out, there are also things of a more structural nature. A good example can again be found in java.lang.reflect.Method. Here's its constructor:

Method(Class declaringClass,
       String name,
       Class[] parameterTypes,
       Class returnType,
       Class[] checkedExceptions,
       int modifiers,
       int slot,
       String signature,
       byte[] annotations,
       byte[] parameterAnnotations,
       byte[] annotationDefault)
  // ...

The constructor expects the generics signature and annotations to be passed in. This poses a dillema. On IKVM looking up the custom attributes that contain this data is relatively expensive and in many cases a method object may be constructed while the code is not interested in generics information or annotations at all, so it might be more desireable to lazily get this data. Another problem is that the annotations are passed in as byte arrays that contain the annotation data as it exists in the class file. Code compiled with ikvmc obviously doesn't have a class file. Despite these two issues, I've chosen to not fork Method. At the moment I think that the performance cost of eagerly getting the generics signature and the annotations is an acceptable trade-off for not having to fork Method. Currently, the way annotations are handled is pretty horrible, because I've left the existing annotation mechanisms in place and reuse the stub class generator code to recreate the annotation byte arrays (and the corresponding constant pool entries) on the fly to pass them into the Method constructor. I've got some ideas to change annotation storage in ikvmc compiled code to use a mechanism that's more compatible with this approach and that may ultimately turn out to be more space efficient as well.


One aspect I haven't talked about yet is compatibility. For example, there's code out there that directly uses ReflectionFactory. This is evil, but it's also reality. So I try to weigh the compability impact as well when I'm trying to find the right approach.

Monday, 04 June 2007 10:46:34 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Thursday, 31 May 2007
First Hybrid OpenJDK / GNU Classpath Snapshot

The first step on a long journey. I've integrated OpenJDK's java.lang.reflect.* a few classes from java.lang.* and a whole bunch of sun.* support classes. Take a look at allsources.lst to see which sources are used from where. I'll try to write a detailed blog entry discussing the various integration points (and answering the questions asked here) over the weekend.

Other changes:

  • Added some conditionally compiled code to work around .NET 2.0 obsoletion warnings.
  • Optimized lcmp, fcmpl, fcmpg, dcmpl and dcmpg bytecodes (by Dennis Ushakov).
  • Fixed ikvmc not to crash if map.xml doesn't contain any <class> entries.
  • Various refactorings to make OpenJDK integration easier.

Known regressions:

  • System class loader is not set correct for ikvmc compiled code.

This is based on OpenJDK drop b12, which appears not to be available for download anymore. The ikvm changes are in cvs. The snapshot binaries are available here: ikvmbin-hybrid-0.35.2707.zip.

As always, snapshots are not intended to be used in production, only for testing and getting a flavor of where development is going.

Thursday, 31 May 2007 16:08:38 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Wednesday, 30 May 2007
IKVM 0.34 Update

I've made an updated 0.34 release that includes the most important fixes I've done in the last couple of weeks.


  • Fixed exception mapping memory leak.
  • Fixed verifier/compiler to support dup_x2 form 2.
  • Fixed for ArrayIndexOutOfBoundsException in generic metadata reflection on dynamically compiled types.
  • Fixed infinite recursion bug when DotNetTypeWrapper.GetName() was used on DerivedType where DerivedType extends BaseType<DerivedType>.
  • Fixed ikvmc generic .NET type loading bug.
  • Fixed Throwable.printStackTrace() to call Throwable.printStackTrace(OutputStream) to support exception classes that only override printStackTrace(OutputStream).
  • Fixed Throwable.printStackTrace(…) to use PrintWriter/PrintStream.println() to trigger flushing on auto-flush writers/streams.
  • Fixed Throwable constructor to set cause correctly if an exception was instantiated but not thrown immediately.

Files are available here: ikvm- (source + binaries) and ikvmbin- (binaries).

Wednesday, 30 May 2007 14:33:14 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Monday, 21 May 2007
Case Studies

A while ago I gave a talk about IKVM at WL | Delft Hydraulics and I convinced them to describe how they use IKVM, for a case study on the IKVM website. My thanks to Fedor and David for taking the time to do this.

If you or your company uses IKVM and would like to write about it for publication on the IKVM website, I would appreciate it very much. Please contact me by e-mail at jeroen@frijters.net.

Monday, 21 May 2007 17:41:19 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Friday, 11 May 2007
Merging the First OpenJDK Code and Another x64 CLR Bug

While working on integrating Sun's recently GPLed code to parse and toString floats and doubles (so that this long standing IKVM bug can finally be fixed) I ran into another x64 CLR bug, this time in the JIT. It was a little bit disturbing to see a Double.parseDouble() test fail with the Sun code that previously worked with my lame and hacked up parsing code, but fortunately the workaround was easy. The IKVM bytecode compiler now obfuscates any -0.0 literals it encounters to prevent the x64 JIT from "optimizing" them.

On a more general note, I haven't yet figured out how to go about integrating the whole of OpenJDK, but I have discovered it'll be quite a bit of work. For every class that uses native code to interface with the VM I'll have to decide whether to implement the existing native methods in C#, implement them in map.xml or rewrite the class to add IKVM specific code. Each option has different trade-offs, for example while it sucks to fork a class due to the added work of merging in changes, adding the required IKVM specific modifications inline is often the cleanest and most efficient way of implementing the required functionality.

I think I'm going to dip my toe into the water by changing my java.lang.reflect.* classes, which are currently modified versions of the GNU Classpath classes, into versions derived from the Sun code.

One final note. The OpenJDK is supposedly licensed under the GPL + "Classpath" exception, but the license text says that only files that explicitly opt-in to the "Classpath" exception are covered by the exception. That implies that I'll have to examine each source file to make sure it is covered, before including it with IKVM.

Friday, 11 May 2007 16:17:15 (W. Europe Daylight Time, UTC+02:00)  #    Comments [3]
# Wednesday, 09 May 2007
Custom Attribute Annotations

Custom attributes are a powerful capability of the .NET Framework and unlike Java annotations, there are quite a few custom attributes that are understood directly by the CLR runtime engine, for example things like P/Invoke, declarative Code Access Security and declaring thread or context local static variables can all be done by applying custom attributes. In addition to this there are also lots of reflection based applications of custom attributes because they've been part of the platform since day one.

Because of the importance of custom attributes, it makes sense to try to support them in ikvm. It has been possible for quite a while to apply custom attributes to Java classes, methods and fields by specifying them in the map.xml file and previously I used this when compiling IKVM.GNU.Classpath.dll in a few places (e.g. for declaring a thread local static variable), but given the similarity between custom attributes and Java annotations (which, like many other Java 5 features, were obviously "inspired" by .NET) it only makes sense to try to map custom attributes to annotations whenever possible.

I started working on this a while ago and recently checked in major improvements to this. The feature is now started to take shape nicely.


Although conceptually very similar, there are significant differences between .NET custom attributes and Java annotations. The most important one is that custom attributes are classes while annotations are interfaces, as a direct result of that custom attributes use a constructor invocation syntax (plus the ability to set fields and properties), while annotations just name the type and list a number of key/value pairs (very similar to custom attribute properties). This means that in .NET, a custom attribute can specify which parameters are required and which are optional, by making the required parameters constructor arguments and the optional ones properties (or fields) and additionally, because of constructor overloading multiple combinations are possible. Annotation can specify for each individual property if it is required or optional, but there is no mechanism similar to constructor overloading.

This leads to the first limitation: Currently only custom attributes that have a default constructor or a single one-argument constructor (taking a supported type) are supported.

The second limitation is that not all parameter types are supported, only the Java primitive types (where Java's byte maps to System.Byte), type literals, strings and enumerations are supported (and single dimensional arrays of these types). Custom attribute parameters typed as Object are not supported.

Nested Annotation Type

When viewed from Java, every supported custom attribute class will appear to have a nested annotation type named Annotation. Here's an example of applying a simple custom attribute annotation to a field:

public class Foo
  private static int threadLocalCounter;

I toyed with the idea of naming the annotation by chopping of the Attribute part, to make it consistent with common C# usage, but I ultimately I decided the nested type approach was better. It's a bit more verbose, but it's consistent with how delegates are handled and it greatly reduces the chance of name clashes.

Single Argument Constructor

If a custom attribute has a single argument constructor, that will be translated into an annotation property named value. This allows the simplified syntax to be used:

public class Foo { ... }

If the custom attribute also has a default constructor, the value property will be optional.


Since .NET enums are value types and behave like integral types most of the time, they are not mapped to Java enums, but for use in annotations they have to be mapped to Java enums, so every .NET enum type has a nested type __Enum that is a Java enum. This allows enum values to be used in annotations:

import cli.System.*;

public class MyCustomAttribute extends Attribute
{ ... }

The above example also shows that an enum that has a FlagsAttribute (as AttributeTargets does) will be translated into an array of that enum, to allow combining the flags. The exception to this is that if the parameter type is already an array, it will not be turned into a two dimensional array, because annotations only support one dimensional arrays.

ValidOn & AllowMultiple

Custom attribute annotations are annotated with the Target and Retention annotations. The target element types are based on the ValidOn property of the AttributeUsageAttribute of the custom attribute and Retention always has a RetentionPolicy.RUNTIME.

The ValidOn property of AttributeUsageAttribute is of type AttributeTargets. Here's a table that shows how the values map to the Java ElementType enum:

System.AttributeTargets java.lang.annotation.ElementType
Assembly, Class, Delegate, Enum, Interface, Struct     TYPE

Unlike custom attributes, annotations cannot be applied to a method's return value. The workaround for that is to nest them inside a special __ReturnValue annotation that is applied to the method:

public class Foo
  public int foo() { ... }

Another custom attribute feature not supported by annotations is the ability to specify multiple instances of a custom attributes (controlled by the AllowMultiple property of AttributeUsageAttribute). This is handled in a similar way:

import cli.System.Security.Permissions.*;

  @UIPermissionAttribute.Annotation(value = SecurityAction.__Enum.Demand,
    Window = UIPermissionWindow.__Enum.SafeTopLevelWindows),
  @UIPermissionAttribute.Annotation(value = SecurityAction.__Enum.LinkDemand,
    Clipboard = UIPermissionClipboard.__Enum.AllClipboard)
public class Foo { ... }

Note that __Multiple is never nested inside a __ReturnValue, when a custom attribute has AllowMultiple and can be applied to return values, the __ReturnValue annotation simply has an array value property.

Type Literals

Type literals can be specified as class literals:

import cli.System.Runtime.CompilerServices.*;

interface assembly {}

Note that the assembly type in the default package is treated specially by ikvm and acts as a placeholder for custom attributes that should be applied to the assembly.

Default Values

This table lists the default values for each supported type:

Type Default Value
boolean      false
byte (byte)0
char (char)0
short (short)0
int 0
float 0.0F
long 0L
double 0.0D
String ""
Class ikvm.internal.__unspecified.class
Enum __unspecified
array { }

The __unspecified hacks are necessary because annotation property values cannot be null. Every __Enum has an __unspecified field specifically for this purpose. Note that these defaults do not necessarily correspond to the real default values used by the custom attribute. These are simply the values that are reported by Method.getDefaultValue() and put into the stubs generated by ikvmstub. If you don't specify a value for an optional property, the resulting custom attribute won't have the property set and hence it will have the default value as defined by the implementation of the custom attribute.

Error Handling

Not yet implemented, but the idea is to ignore invalid annotations (most likely due to version conflicts between the stub jar that the Java code was compiled against and the assembly used at runtime). In the case of ikvmc, a warning message should be emitted as well.

Wednesday, 09 May 2007 08:15:26 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
New Snapshot

I expect that I'll be busy the next couple of weeks working on integrating the OpenJDK libraries that were released yesterday, so I thought I'd release a new development snapshot to reflect the current state. There are quite a few bug fixes, most of them triggered by running test suites suggested by Albert Strasheim. Many thanks to him for running the test suites and passing the interesting ones on to me (including instructions on how to install/build/run them, which is usually the most time consuming and frustrating part.)

This snapshot also includes much improved support for applying .NET custom attributes as Java annotations. The next blog entry will describe the changes in detail.


  • Integrated current GNU Classpath cvs version.
  • Fixed exception handling to continue working during AppDomain finalization for unload.
  • Implement major chunk of custom attribute as annotations support.
  • Added support for applying custom attributes to return values.
  • Added support for applying AllowMultiple custom attributes multiple times to the same element.
  • Restructured ParameterBuilder handling.
  • Added system property "ikvm.apartmentstate" to enable setting the COM ApartmentState for threads created in Java code.
  • Added hack to support Double.MIN_VALUE and Double.MAX_VALUE toString/parse roundtripping.
  • Fixed Throwable.printStackTrace() to call Throwable.printStackTrace(OutputStream) to support exception classes that only override printStackTrace(OutputStream).
  • Fixed Throwable.printStackTrace(…) to use PrintWriter/PrintStream.println() to trigger flushing on auto-flush writers/streams.
  • Fixed Throwable constructor to set cause correctly if an exception was instantiated but not thrown immediately.
  • Moved ikvmc warning handling to fix missing warnings bug (previously depending on compilation order, some warnings might not be shown).
  • Fixed verifier/compiler to support dup_x2 form 2. Found by Derby test suite.
  • Implemented JSR 133 rule that says that finalize cannot run before constructor is finished.
  • Fixed ArrayIndexOutOfBoundsException in generic metadata reflection on dynamically compiled types.
  • Fixed PlainDatagramSocketImpl to set initial SO_BROADCAST option to enabled.
  • Fixed PlainSocketImpl.getOption(SO_OOBLINE) to return Boolean instead of Integer.
  • Fixed DatagramChannelImpl to reflect connectedness on underlying DatagramSocket.
  • Fixed SocketChannelImpl.read(ByteBuffer) to handle -1 return values from implRead() for non byte array backed buffers.

Binaries available here: ikvmbin-0.35.2685.zip

Wednesday, 09 May 2007 08:13:44 (W. Europe Daylight Time, UTC+02:00)  #    Comments [3]
# Saturday, 05 May 2007
IKVM 0.34 Released

I released to SourceForge (same bits as rc3).

Saturday, 05 May 2007 09:35:10 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]