# Thursday, 19 August 2004
Article on IKVM

Avik Sengupta wrote an excellent article on IKVM.

Thursday, 19 August 2004 13:33:47 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Tuesday, 17 August 2004
New Snapshot

A new development snapshot. I made many changes (way too many) since the last snapshot. The diff was over 13,000 lines (and I had already checked in part of the changes).

This is an important step towards 1.0, but there is still much to be done.

BTW, Eclipse 3.0 starts up with this version, but that's pretty much it, it doesn't do anything useful yet.

What's New:

  • Changed version numbers to 0.9.* (I'm using a Linux kernel version scheme, even numbers are used for releases, odd numbers are used during development.)
  • Resynchronized with GNU Classpath cvs.
  • Made String.compareTo(Object) redirect to my own implementation instead of System.String.CompareTo (including when the method is invoked through the java.lang.Comparable interface, which is still remapped to System.IComparable).
  • Fixed exception remapping handling of java.lang.ExceptionInInitializer.
  • Added dummy (but safe) implementations of getHostAddress and hostsEqual to ikvmres protocol handler.
  • Removed work around for Classpath serialization bug from Throwable cause serialization. The state of whether the cause was set is now properly serialized.
  • Fixed deserialization of exceptions serialized with pre-1.4 JDKs.
  • Fixed integer overflow bugs in the various argument tests in the String(byte[], ...) constructors.
  • Added missing argument check to String.startsWith(String prefix, int offset).
  • Added -Xbreak option to ikvm, to fire the debugger on startup.
  • Added support for automatically generating build and revision numbers to ikvmc (e.g. -version:0.9.*)
  • Fixed ikvmstub bug that caused invalid max_locals to be set in constructor definitions if the constructor took long or double arguments.
  • Fixed visibility handling of nested types. A public nested type nested inside a non-public type was incorrectly treated as public.
  • Fixed reflection bug. Statically compiled classes had private methods incorrectly reported as final.
  • Fixed method override resolver bug. Having a private final method in a base class with a similar name/signature as a virtual method in the subclass caused a VerifyError (which was presented as a critical failure).
  • Fixed another method override resolver bug. Only interfaces implemented by direct base class were searched, not those implemented by all base classes.
  • Added workaround for deserializing incorrectly serialized java.lang.String objects (strings are supposed to be special cased by serialization, but if you manually construct a serialization stream that contains a TC_OBJECT of class java.lang.String, previously you'd get a weird exception.)
  • Added (untested) implementation of VMAccessController.
  • Fixed small compiler bug. Ldarg/Starg instruction was emitted with int argument, instead of short. This caused two bogus nops in the CIL stream to follow each Ldarg/Starg instruction (in exceptional cases).
  • Fixed Tracer to handle messages without formatting characters.
  • Fixed lame typo in JVM.CompilerClassLoader.EmitRedirect. (Call to Debug.CompareTo(...) instead of System.Diagnostics.Debug.Assert(...)).
  • Added nonvirtualAlternateBody support to map.xml parser.
  • Added nonvirtualAlternateBody to map.xml for java.lang.Object.toString().
  • Added exceptionBlock support to map.xml parser.
  • Added exception handler to map.xml for java.lang.ThreadDeath exception mapping code, to catch ThreadStateException if Thread.Abort is called while it isn't required.
  • Removed unnecessary path name check from FileChannelImpl.open().
  • Removed VMFile.demangle(). Normalization is now part of Classpath java.io.File.
  • Added exception handling to VMFile.isHidden().
  • Added VMFile.toCanonicalForm(). Now used by Classpath java.io.File.getCanonicalPath().
  • Added protection domain support to VMClass.createClass().
  • Removed VMClass.loadBootstrapClass().
  • Removed unused deprecated version of VMClassLoader.defineClass().
  • Added bootstrap classloader resource support to VMClassLoader.
  • Implemented VMClassLoader.getSystemClassLoader() in VMClassLoader. The system classloader is now always available, not just if the application was started with ikvm.exe.
  • Added app.config appSettings support to VMRuntime.insertSystemProperties(). Java properties can now be specified in your .NET application .config file:
    <appSettings>
       <add key="ikvm:<propertyname>" value="<propertyvalue>" />
    </appSettings>
  • In VMThread, removed cleanupDataStoreSlot static and always do lookup of the LocalDataStoreSlot by name, to handle scenario where the IKVM main thread is the first one to lookup the LocalDataStoreSlot (and previously that would cause the static initializer of VMThread to fail, because AllocateNamedDataSlot would fail, as the name was already in use).
  • Fixed Field.checkAccess() when caller is a global method.
  • Removed ExtClassLoader and AppClassLoader from starter.cs (ikvm.exe).
  • Added hack to set the priority of the ikvmdump.exe writing thread to AboveNormal, to deal with a spinning thread in Eclipse on shutdown.
  • Don't add CLASSPATH to java.class.path is the -jar option is specified.
  • Removed support for DLLs in the bootclasspath.
  • Fixed exception handling compilation options for IKVM.JNI.CLR-Win32 in clr-win32.build.
  • Major rewrite of local and global ref support in Win32 JNI provider.
  • Implemented most of the remaining JNI functions in Win32 JNI provider.
  • Fixed class file parser to disallow native constructors.
  • Rewrote class loading and method/field linking in ClassFile.cs.
  • Fixed most of the thread safety issues in class loading/reflection.
  • The runtime no longer throws Java exceptions, instead it throws its own exception, which are converted to Java exceptions at the runtime/Java boundaries. This makes ikvmc compilation of Classpath more robust (previously, if an exception required by the runtime was missing, it would often result in infinite recursion).
  • Simplified MethodDescriptor. It is now only a name/signature tuple.
  • MethodWrapper now uses virtual methods instead of delegates to emit call/callvirt/newobj sequences.
  • Major rewrite of method resolving/linking and MethodWrapper infrastructure. Loader constraints are now properly enforced and LinkageErrors are thrown in the right places at the right times.
  • Renamed HideFromReflectionAttribute to HideFromJavaAttribute and made the semantics consistent. It now means that the method is totally invisible from Java (either through reflection or statically). The new MirandaMethodAttribute signals that a method is invisible from reflection, but callable by Java byte code.
  • Added new NameSigAttribute that is used to recover the original method name or signature when a method name is mangled or when a signature is changed in such a way that at runtime the original signature cannot be reconstructed anymore.
  • Fixed TypeWrapper.IsInSamePackage() to understand that a package with the same name but in different assemblies, really isn't the same package.
  • Fixed ininst instruction in map.xml. Now works the same for Java and .NET types.

I'm sure I forgot many changes/fixes. This change set was just too large. I promise to check in more frequently in future :-)

New snapshots: just the binaries and source plus binaries.

Tuesday, 17 August 2004 11:08:03 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Monday, 16 August 2004
JavaScript on IKVM

Phil blogs about running Rhino on IKVM on Mono.

Monday, 16 August 2004 17:26:15 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Tuesday, 10 August 2004
Whidbey, Generics, Co- and contravariance

I came across an interesting Whidbey beta 1 CLR feature today. As far as I can tell this hasn't been documented anywhere yet, but the Whidbey beta 1 CLR supports covariant and contravariant generic type parameters.

This is a really interesting feature. If C# would support it (at the moment it doesn't), you'd be able to do something like this:

interface IReader<T>
{
  T Get(); 
}
interface IWriter<T>
{
  void Put(T t);
}
class Test<T> : IReader<T>, IWriter<T>
{
  T t;
  public T Get() { return t; }
  public void Put(T t) { this.t = t; }
}
class Driver
{
  static void Main()
  {
    Test<string> t1 = new Test<string>();
    t1.Put("covariance");
    IReader<object> rdr = t1;
    Console.WriteLine(rdr.Get());
    Test<object> t2 = new Test<object>();
    IWriter<string> wrtr = t1;
    wrtr.Put("contravariance");
    Console.WriteLine(t2.Get());
  }
}

Notice that in the first highlighted line we're assigning an object reference that implements IReader<string> to a local variable of type IReader<object>. This is covariance and it is type safe because the IReader<T> interface only returns T. In the second highlighted line we assign a reference that implements IWriter<object> to a local of type IWriter<string>, this is contravariance and this is also type safe, because IWriter<T> only accept arguments of type T.

Unfortunately, C# doesn't yet seem to support this feature, but if we manually write the IL, it'll run on the Whidbey beta 1 CLR (and it is fully verifiable):

.assembly extern mscorlib {}
.assembly test {}

.class interface public abstract
      'IReader`1'<+([mscorlib]System.Object) T>
{
  .method public abstract instance
          !T Get() cil managed {}
}

.class interface public abstract
      'IWriter`1'<-([mscorlib]System.Object) T>
{
  .method public abstract instance
          void Put(!T t) cil managed {}
}

.class public 'Test`1'<([mscorlib]System.Object) T>
      extends [mscorlib]System.Object
      implements class 'IReader`1'<!T>,
                 class 'IWriter`1'<!T>
{
  .field private !T v

  .method public virtual instance
          !T Get() cil managed
  {
    ldarg.0
    ldfld !0 class 'Test`1'<!T>::v
    ret
  }

  .method public virtual instance
          void Put(!T t) cil managed
  {
    ldarg.0
    ldarg.1
    stfld !0 class 'Test`1'<!T>::v
    ret
  }

  .method public specialname rtspecialname
          instance void .ctor() cil managed
  {
    ldarg.0
    call instance void [mscorlib]System.Object::.ctor()
    ret
  }
}

.method static void Main(string[] args) cil managed
{
  .entrypoint
  .locals init ([0] class 'Test`1'<string> t1,
                [1] class 'IReader`1'<object> rdr,
                [2] class 'Test`1'<object> t2,
                [3] class 'IWriter`1'<string> wrtr)

  newobj instance void class 'Test`1'<string>::.ctor()
  stloc.0
  ldloc.0
  ldstr "covariance"
  callvirt instance void class 'Test`1'<string>::Put(!0)
  ldloc.0
  stloc.1
  ldloc.1
  callvirt instance !0 class 'IReader`1'<object>::Get()
  call void [mscorlib]System.Console::WriteLine(object)

  newobj instance void class 'Test`1'<object>::.ctor()
  stloc.2
  ldloc.2
  stloc.3
  ldloc.3
  ldstr "contravariance"
  callvirt instance void class 'IWriter`1'<string>::Put(!0)
  ldloc.2
  callvirt instance !0 class 'IReader`1'<object>::Get()
  call void [mscorlib]System.Console::WriteLine(object)
  ret
}
 

Notice the plus and minus signs in the interface declarations to signal that a generic type parameter is covariant or contravariant.

Tuesday, 10 August 2004 16:03:46 (W. Europe Daylight Time, UTC+02:00)  #    Comments [6]
# Wednesday, 30 June 2004
Mono 1.0

Congratulations to the Mono team with the release of 1.0!

Wednesday, 30 June 2004 19:03:12 (W. Europe Daylight Time, UTC+02:00)  #    Comments [2]
Finally a Real Web Site

Many thanks to Brian J. Sletten and Stephen Schaub for building the new IKVM.NET web site. I will continue to write this blog, but from now on instructions, documentation and howto articles will appear on the new site (in addition to the excellent content that is already there), where they'll have a more permanent home than here on the blog.

Update: The samples made by Brian and Stephen are available for download on SourceForge now as well.

Wednesday, 30 June 2004 14:34:50 (W. Europe Daylight Time, UTC+02:00)  #    Comments [3]
# Monday, 28 June 2004
Release Candidate 1

I changed the version number on all assemblies (except for IKVM.GNU.Classpath) to 0.8.0.0 and tagged the cvs tree with v0_8_0_0 and put the files up on the SourceForge download site: Source and binaries or just binaries.

Unless any last minute showstopper bugs are found, this will be the version shipped with Mono 1.0.

Other changes:

  • IKVM.Runtime.dll, IKVM.GNU.Classpath.dll, IKVM.JNI.CLR-Win32.dll and IKVM.JNI.Mono.dll are now signed to enable putting them in the GAC.
  • Fixed java.lang.Object method invocation through ghost interface references.
  • Changed JNI provider loading to use LoadWithPartialName, to support loading the JNI provider from the GAC.
Monday, 28 June 2004 14:07:22 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Friday, 25 June 2004
Yet Another Snapshot

More fixes...

Changes:

  • Fixed bug in String.indexOf(int), String.lastIndexOf(int), String.indexOf(int, int) and String.lastIndexOf(int, int). When a character outside of the valid character range was passed, it was truncated to a character instead of returning -1.
  • Changed VMThread.holdsLock implementation to use Monitor.Pulse instead of Monitor.Wait to check for monitor ownership. This can cause spurious wakeups from Object.wait(), but according to the new JDK 1.5 memory model that is allowed, and it has always been good coding practice to guard against spurious wakeups. Thanks to Dalibor Topic for researching this issue.
  • Fixed reflection to properly check accessibility for protected instance fields and methods.
  • Partially implemented JNI method JavaVM::AttachCurrentThread (only on Windows). It only supports "attaching" a thread that already is a Java thread. This was required for the latest SWT 3.0 versions .
  • Fixed bug in handling of ghost and value return types for statically compiled code. Among possible other problems, this caused String.subSequence to behave oddly.
  • Improved support for reflection on .NET enums. The (fake) Value field and wrap() method are now available through Java reflection.
  • Added name mangling for enums that happen to contain a Value value.
  • Added a few try/finally blocks for Profiler.Enter/Leave calls in compiler.cs.
  • Added profiler counter for inserted interface down casts.
  • Added bge_un, ble_un, ldc_i4 and ldc_i4_m1 opcodes to remapper.cs.
  • Fixed a verifier bug in merging value type array types.
  • Removed optimization from verifier related to interface type merging. The optimization reduced the number of downcasts that had to be inserted in the code, but it turned out that ECMA interface type merging rules didn't allow this optimization.
  • Fixed integer overflow bugs in String.regionMatches() and String.lastIndexOf(String, int).
  • Fixed bug in array type visibility for array types constructed from statically compiled (or .NET) nested types.

New snapshots: just the binaries and source plus binaries.

Friday, 25 June 2004 16:14:06 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Sunday, 20 June 2004
A Couple More Fixes

A new snapshot with a few small fixes and bigger fix to support serialization of Throwable. Since java.lang.Throwable is a remapped type, it's fields don't really exist and therefor didn't get serialized (and I had totally failed to realise this). It turned out to be easy to add serialization support (compatible with Sun's serialization of Throwable) by using the (previously unknown to me) feature of serialization to manually do serialization in a way that is compatible with the default serialization implementation.

Changes:

  • Fixed ikvm.exe regression that caused it to fail to invoke main on package private classes. (Caused by reflection fix in the previous snapshot).
  • Added (small) hack to reflection invoke to support deserialization of java.lang.Throwable (and subclasses).
  • Fixed (de)serialization of java.lang.Throwable.
  • Fixed small bug in Throwable.initCause(). Previously, if an exception was constructed and null was passed as the cause, you could later on use initCause() to change the cause.
  • Added ldlen opcode to remapper.cs
  • Fixed String.copyValueOf(char[]) to throw NullPointerException if array is null.
  • Fixed String(char[]) constructor to throw NullPointerException if array is null.
  • Fixed recently introduced reflection regression that (sometimes) causes NullPointerException when getting a method's declared exceptions. This mostly showed up running ikvmstub.

New snapshots: just the binaries and source plus binaries.

Sunday, 20 June 2004 11:04:29 (W. Europe Daylight Time, UTC+02:00)  #    Comments [3]
# Monday, 14 June 2004
Another Snapshot

A new snapshot for inclusion in Mono Beta 3.

Changes:

  • Added box/unbox methods to ikvm.lang.CIL for all primitive types.
  • Added conversion methods for unsigned CLI primitive types to ikvm.lang.CIL.
  • Changed FileChannelImpl to call stream.WriteByte, which is now possible because of the new unsigned primitive support in ikvm.lang.CIL.
  • Rewrote a large part of reflective method invocation to fix all known issues. Reflection on remapped types now works as well as full support for ghost types (both in calling methods through ghost interfaces, as well as passing or returning ghost references).
  • Added support for a few more opcodes to remapper.cs.
  • Added error handling for unsupported elements in remapping file (map.xml).
  • Fixed reflection to take visibility of class into account.
  • Fixed class file validation rules to ignored strictfp on abstract methods (according to the VM spec it isn't allowed for an abstract method to be strictfp, but javac is broken and sets the strictfp modifier for abstract method too and Sun's JVM obviously doesn't enforce this part of the spec).
  • Fixed JNI AllocObject to work correctly for java.lang.Object and java.lang.Throwable.

New snapshots: just the binaries and source plus binaries.

Monday, 14 June 2004 20:12:18 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]