# Friday, 18 February 2005
Snapshot

Mostly bug fixing and a couple of work arounds for bugs in the CLR and Mono.

Changes:

  • Sync'ed with GNU Classpath cvs.
  • Fixed bug in ClassLoaderWrapper that caused exception when defining the ModuleBuilder if the first class loader to define a class had a toString() representation that contained characters that are illegal in an assembly name.
  • Changed System.identityHashCode implementation to use non-virtual call to Object.GetHashCode instead of RuntimeHelpers.GetHashCode, to work around .NET runtime bug.
  • Fixed reflection to support modifying final instance fields (as per JSR-133).
  • Added optional verbose cast failure messages (set the IKVM_VERBOSE_CAST environment variable to enable this).
  • Fixed unloadable type support in native method signatures.
  • Changed handling of delegate types that have unsupported types in method signature (inner interface is no longer generated). This fixes bug 1119575.
  • Added -enabletls option to ikvmc to automagically add ThreadStaticAttribute to fields starting with __tls_
  • Changed IKVM specific Classpath methods to use __tls_ fields instead of LocalDataStoreSlot. This improves performance, but also works around a bug in the CLR relating to AppDomain shutdown and a GC bug in Mono on Windows.
  • Added workaround for Mono bug in GCHandle.IsAllocated.
  • Fixed implicit interface downcasting (which is sometimes required due to a quirk in the JVM spec) to throw IncompatibleClassChange instead of ClassCastException.
  • Fixed bug in argument globbing code that caused command line of statically converted executables to start with the name of the executable (in args[0]) on unix.
  • Fixed bug that caused Thread.join() on main thread to hang.
  • Fixed JNI name mangling to support encoding Unicode and special characters correctly.
  • Fixed JavaException to not call String.Format on non-format strings.
  • Optimized VMThread.jniDetach to not do anything if a Java thread object was never created.

New snapshots: just the binaries and source plus binaries.

Friday, 18 February 2005 13:18:32 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Tuesday, 08 February 2005
Weird Bug

Jamie Cansdale reported a strange problem on the mailing list. His code ran successfully when run for the first time, but subsequent runs in the same process, but a different AppDomain failed with a ClassCastException.

He was kind enough to work with me to try and isolate the problem. So several hours and various private IKVM builds later, I was able to reproduce the root problem:

using System;
using System.Runtime.CompilerServices;
class Class1
{
  static void Main(string[] args)
  {
    RuntimeHelpers.GetHashCode(new Class1());
    if(AppDomain.CurrentDomain.FriendlyName != "2nd")
    {
      AppDomain dom = AppDomain.CreateDomain("2nd");
      dom.ExecuteAssembly(typeof(Class1).Assembly.Location);
    }
  }
}

This code dies with a System.MissingMethodException! Yet another weird multi-AppDomain bug.

Fortunately, the work around is easy. Instead of using RuntimeHelpers.GetHashCode() to implement System.identityHashCode(), I've gone back to using some handcoded IL in map.xml to call System.Object.GetHashCode() non-virtually. This was also what I did on v1.0 of the CLR (where RuntimeHelpers.GetHashCode() didn't yet exist).

Tuesday, 08 February 2005 14:52:47 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Wednesday, 02 February 2005
New Snapshot

Lot's of changes, but the major one is that Java's primitive type byte is now mapped to System.Byte instead of System.SByte. This makes interoperability between Java and other .NET code much easier (since System.Byte is in the CLS), although you have to be a little careful because Java's byte is signed and System.Byte is unsigned.

Changes:

  • Changed assembly versions to 0.11.*
  • Sync'ed with GNU Classpath cvs.
  • Added hack to support new Classpath awt event model.
  • Changed mapping of Java primitive byte from System.SByte to System.Byte, to remove the need for ByteArrayHack and better/easier interop with CLS code.
  • Regenerated mscorlib.jar, System.jar and System.Xml.jar with new ikvmstub (to deal with the new byte <-> System.Byte mapping).
  • Added optional support for compiling GNU Classpath with ecj to the build script. NOTE: The ecj -1.5 option is used to generate 1.5 compatible class files, so you must set the IKVM_EXPERIMENTAL_JDK_5_0 environment variable prior to starting the build process. When ecj is used to compile GNU Classpath with the -1.4 option, the build will fail because the resulting assembly is not verifiable. This is because ikvmc doesn't currently handle the way ecj compiles Java 1.4 class literals when used in the invocation of a base class constructor (this obviously isn't a common scenario, but it will be supported in a future version).
  • Added partial support for the new Java 5 StringBuilder class.
  • Changed the ikvm.lang.CIL boxing/unboxing methods dealing with bytes to account for the changed mapping.
  • Deprecated ikvm.lang.ByteArrayHack (it now contains only a single cast method that "casts" from byte[] to byte[], it will be removed in a future version).
  • Added ugly workaround for return type covariance in the IResourceReader interface.
  • Cleaned up setting the thread group when attaching a native thread.
  • Fixed JNI direct buffer APIs to support all types of java.nio.Buffer, not just ByteBuffer.
  • Implemented VMClassLoader.getPackages() to support enumerating packages defined by the bootstrap class loader. This is currently disabled on Mono due to a bug in Assembly.GetTypes() on Mono 1.0.5 and 1.1.3.
  • Implemented new stack walking mechanism that fully supports skipping over reflection and native stack frames.
  • Changed reflection to use new stack walking mechanism.
  • Changed native library loading to use new stack walking mechanism.
  • Fixed ikvmstub to return error value if it fails.
  • Added optional support to the build script to build a AMD64 version of JVM.DLL.
  • Fixed DynamicInvokeVirtual to actually do a virtual method invocation, instead of a non-virtual invocation.
  • Collapsed TypeWrapper.TypeAsParameterType and TypeWrapper.TypeAsFieldType into a single new property TypeWrapper.TypeAsSignatureType.
  • Fixed JNI_CreateJavaVM to support all valid JNI versions.
  • Fixed JNI DestroyJavaVM to return success when "destroying" the VM (even though -- like Sun -- we don't support actually destroying the VM).
  • Fixed JNI DetachCurrentThread to return success when detaching an already detached thread.
  • Fixed JNI FindClass to reject class names with dots and added support for signature format class names (e.g. [Ljava/lang/Object;), it also throws NoClassDefFoundError now instead of ClassNotFoundException.
  • Made some minor tweaks to JNI local ref allocation algorithms.
  • Changed reflective non-virtual method invocation to do a virtual invocation when invoking interfaces methods (for compatibility with Sun) and to use the regular reflection code path when invoking non-virtual methods or virtual methods that are guaranteed not to be overridden.
  • FieldWrapper.EmitGet/EmitSet and MethodWrapper.EmitCall[virt] no longer convert the field/return value from SignatureType to StackType, this is now left to the caller.
  • Fixed regression that could cause TypeWrapper constructor to try to construct a Class object for unloadable types (and this could result in an exception when an unloadable array type was constructed).
  • Renamed method TypeWrapper.EmitConvParameterToStackType to TypeWrapper.EmitConvSignatureTypeToStackType
  • Renamed method TypeWrapper.EmitConvStackToParameterType to TypeWrapper.EmitConvStackTypeToSignatureType.
  • Fixed native method invocation stubs to handle ghost types correctly.
  • Fixed reflection on .NET types to report Sealed and Abstract types as abstract only (the final abstract combination isn't legal in Java).
  • Improved handling of clashing method names for private interface methods.
  • Improved generation of base type method "hiders" for remapped types to support additional method overloads on Whidbey.

New snapshots: just the binaries and source plus binaries.

Wednesday, 02 February 2005 16:40:19 (W. Europe Standard Time, UTC+01:00)  #    Comments [2]
# Thursday, 13 January 2005
0.10 Released

I put the 0.10 release version on SourceForge, it's identical to rc2 and be downloaded here.

Thursday, 13 January 2005 12:50:24 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Monday, 10 January 2005
0.10 Release Candidate 2

I decided to make a new release candidate to fix a couple of bugs to make ecj work better.

It's available here: binaries and source plus binaries.

Note that IKVM still has a bug that causes a particular code construct that ecj generate to be compiled into unverifiable (but working) code. The code construct is using a class literal in the invocation of a base class constructor, ecj compiles this with inline code (javac and jikes put the generated code in a new method) and code has an exception handler around the Class.forName(), but the CLI doesn't allow exception handlers before the base class constructor is called.

Changes:

  • Added ikvm/lang/ByteArrayHack.java, ../../classpath-0.13/vm/reference/java/lang/VMCompiler.java and ../../classpath-0.13/gnu/java/awt/peer/GLightweightPeer.java to classpath/allsources.lst. Jikes automatically added these files, but when compiling with ecj the list needs to be complete (which is actually much nicer, since it doesn't require the classpath to be set in addition to the list of source files).
  • Added support for IKVM_EXPERIMENTAL_JDK_5_0 environment variable to enable Java 5 class file format support (note that since none of the JDK 5.0 APIs are available this isn't very useful, except for experimentation).
  • Fixed several bugs in Double.parseDouble/Float.parseFloat.
Monday, 10 January 2005 15:27:36 (W. Europe Standard Time, UTC+01:00)  #    Comments [2]
# Friday, 07 January 2005
0.10 Release Candidate 1

I finally decided to make a long overdue new release (releases are what you download from the IKVM SourceForge project download and are better tested and include signed binaries). When I release a new development snapshot, I usually test it by running Mauve and my ikvm specific tests and by starting up Eclipse. I build my code on Windows using the Microsoft .NET Framework 1.1 and I don't generally test them on Mono on Linux. Releases are tested on Mono (although fairly superficially, since many of my tests don't run on Mono yet) and more importantly, for a release I also make sure that you can build IKVM on Mono on Linux. In a stroke of irony, while I was testing this release candidate, I discovered that my workaround for the Mono metadata bug that I introduced yesterday actually causes Mono to crash when building IKVM.GNU.Classpath.dll (the workaround itself works, you can run a Windows built IKVM.GNU.Classpath.dll that includes the workaround on Mono), so I added a workaround for that as well.

Basic info:

  • This releases is based on the GNU Classpath 0.13 release. Get it here.
  • It was tested on .NET Framework 1.1 on Windows, Mono 1.0.5 on Debian 3.0 and Mono 1.1.2 on Debian 3.0
    (I couldn't get Mono 1.1.3 to build, so I only tested with 1.1.2)
  • Downloads: binaries and source plus binaries.
  • Japi results: JDK 1.4 vs IKVM 0.10.0.0 and IKVM 0.10.0.0 vs JDK 1.4.
  • This is still a release candidate, but if no major problems are found it will be released as is.

Building from source:

  • Download and unzip the IKVM source zip file.
  • Download GNU Classpath 0.13 and extract it in a directory next to the ikvm directory. You don't need to run any of the makefiles or build scripts.
  • Make sure you have NAnt-0.84 and Jikes 1.22 installed.
  • Make sure you have the Microsoft .NET Framework 1.1, Mono 1.0.5 or Mono 1.1.2 installed.
  • cd ikvm
  • nant
  • That's it!

Changes:

  • Added workaround for Mono Reflection.Emit bug that causes NullReferenceException when emitting empty properties.
  • Added ikvmc -key:<keycontainer> option.
  • Added "signed" target to main build file, to automatically sign all assemblies.
  • Changed all version numbers to 0.10.0.0.
  • Signed all assemblies.
  • Tagged the cvs tree with v0_10_0_0.
Friday, 07 January 2005 13:47:31 (W. Europe Standard Time, UTC+01:00)  #    Comments [1]
# Thursday, 06 January 2005
ecj

Stuart Ballard posted instructions on his blog on how to build ecj (the Eclipse Compiler for Java) and compile it into an executable with ikvmc.

This is really cool, because ecj is an open source pure-Java compiler that supports all of the Java 5.0 features.

Thursday, 06 January 2005 21:24:58 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
New Snapshot

I added a workaround for the Mono metadata bug and made a couple of other changes, most notably the -opt:fields ikvmc option to remove unused private static fields (except for serialVersionUID), this makes the generated IKVM.GNU.Classpath.dll about 1MB smaller, because of the large number of string constant fields in the locale table classes. I haven't investigated this fully, but it appears that string literals in the code are in a different heap than the string field literals and thus they end up in the file twice. If this is indeed true than it is a rather unfortunate design flaw in the CLI metadata spec (especially since you're not allowed to use the CIL ldsfld instruction on a literal field).

Changes:

  • Sync'ed with GNU Classpath cvs.
  • Added empty NetToolkit.createRobot method (to make it compile with recent Classpath change).
  • Only do the MethodBuilder private field scrubbing hack if we're on .NET 1.1
  • Added -opt:fields ikvmc option to remove unused private static fields.
  • Added -monoBugWorkaround option to ikvmc (and added it to the IKVM.GNU.Classpath.dll build file) to workaround Mono 1.0.5 and 1.1.3 metadata bug. Only use this option if your compiled exe/dll fails to load on Mono (this happens if it has more than 32768 methods), it causes the generated file to grow by about 300KB.
  • Added workaround for NullReferenceException in Thread.SetData() on Mono.

New snapshots: just the binaries and source plus binaries.

Thursday, 06 January 2005 11:46:32 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Wednesday, 05 January 2005
Mono Problems

Just a quick entry to point out problems with the most recent development snapshot on Mono. Mono gives a bunch of assertion failures:

** (ikvm.exe): CRITICAL **: file metadata.c: line 804 (mono_metadata_string_heap): assertion `index < meta->heap_strings.size' failed

** (ikvm.exe): CRITICAL **: file metadata.c: line 832 (mono_metadata_blob_heap): assertion `index < meta->heap_blob.size' failed

Not sure what's going on yet, but in the mean time, if you want to run on Mono, you can use the previous snapshot: binaries and source + binaries.

[Update: As usual, Zoltan Varga was on the case and quickly fixed the problem in the Mono 1.0 and 1.1 source trees. He also told me how to workaround it, so the new snapshot has a workaround.]

Wednesday, 05 January 2005 17:37:48 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Tuesday, 04 January 2005
Using IKVM as a JRE with Eclipse

A while ago Howard Gilbert wrote instructions on how to use IKVM as the target runtime with Eclipse (i.e. not running Eclipse in IKVM, but running the code you develop with Eclipse in IKVM).

My apologies to him for not posting this earlier (and for not adding it to www.ikvm.net, where it really belongs).

I could not find instructions in the documentation about using vanilla
Eclipse (under Java) to develop code that you then run (in Eclipse) under
IKVM. The trick is to define IKVM to Eclipse as an additional Java Runtime
Environment. It seems that this might be useful to post somewhere:

[This uses Windows and an installed Microsoft .NET Framework, but it can
probably be adapted.]

Eclipse runs under the default version of Java installed on your machine
(type "java -version" to find out). However, it can be configured with the
directories of other Java Runtime Environments (JRE's). In the Run . panel,
you can select a particular JRE in which to run each application.

Eclipse believes that a directory is a JRE if it has two things. 
1. It must have a {jre}/bin/java.exe file. 
2. It must have a {jre}/lib/rt.jar file.

Start with a binary distribution of IKVM in c:\ikvm. Copy
c:\ikvm\bin\ikvm.exe c:\ikvm\bin\java.exe. Create a c:\ikvm\lib and copy
into it the rt.jar from your favorite real Java runtime. Don't worry
because, of course, it will not really be used.
[Jeroen: You can also run ikvmstub on IKVM.GNU.Classpath.dll and rename the
resulting IKVM.GNU.Classpath.jar to rt.jar]

In Eclipse, pull down the Window menu option and select Preferences - Java -
Installed JRE's. Click the Add... button. Leave the type as "Standard VM". A
suggested "JRE name" is "IKVM". Point the "JRE home directory" to c:\ikvm.

The JRE system libraries box fills up with the libraries found in the
{jre}/lib directory. For the moment, the only such library is rt.jar.

Now build a simple Java program. When you want to run it, select Run - Run
... In the JRE tab, click the "Alternate JRE" option and select IKVM from
the pulldown. If you want to be clear, in the "Java executable" select
Alternate and type in "ikvm" (that is the ikvm.exe program). 

Now run the program. It ran under IKVM, but it is indistinguishable from
Java.

Now run ikvmstub on your favorite version of mscorlib.dll and put the
resulting jar file in c:\ikvm\lib\mscorlib.jar. After that, you should be
able to ikvmc your favorite JAR files, then put the jar file into /lib and
the generated dll into /bin. This is just a suggested use of the library
structure.

Sanity check: The Eclipse Package Explorer displays the JAR files as Eclipse
sees them during compilation. Even if you intend to run the program under
IKVM, Eclipse is going to compile them with your default real Java and its
libraries. So when you add JAR files to c:\ikvm\lib this doesn't put them in
the compiler path. You have to manually add the extra JAR files to your
project, and then the compiler knows to use them as the source is compiled.
At runtime the DLLs will either be automatically located because they are in
the same directory with ikvm.exe. 

So use Project - Properties - Java Build Path - Libraries - Add External
Jars to add mscorlib.jar to your project, and write a small Java program
using some CLI classes. Note that all the usual Eclipse IDE features work.
Type "cli.System.Console." and pause. Eclipse likes (default behavior of a
configurable feature) to convert explicit class names to imports, so it will
add a

import cli.System.Console

to the import group, replace what you have just typed with "Console." and
then display a popup with the list of methods of the System.Console class to
complete the expression.

When it doubt, in the Explorer panel on the left expand any of the jar files
(such as mscorlib.jar) to see the actual fully qualified names of the
classes generated by ikvmc.

Save the file and it gets compiled.

Run it (assuming again you set Run ... to use the IKVM "JRE") and you get
the expected output. Now there is no question that you are running IKVM
because you are calling CLI libraries.
Tuesday, 04 January 2005 09:09:48 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]