# Monday, 09 April 2007
Memory Mapped Files

What happens when you get a read error while accessing a memory mapped file? Let's try it:

RandomAccessFile raf = new RandomAccessFile("\\\\server\\share\\filename", "r");
FileChannel channel = raf.getChannel();
MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_ONLY, 0, 5 * 1024 * 1024);
map.get(10 * 1024);
System.out.println("read byte at 10K -- waiting");
Thread.sleep(5000);
map.get(500 * 1024);
System.out.println("read byte at 500K");

Running this on JDK 1.6 (x64) and removing the network cable during the sleep will result in an Internal Error in the VM. Not exactly what I had hoped for.

Interestingly, on IKVM doing the same results in a cli.System.Runtime.InteropServices.SEHException being thrown.

Monday, 09 April 2007 11:32:31 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
New Snapshot

The GNU Classpath 0.95 release branch has been created (0.94 was skipped), so it shouldn't be long now before I will release IKVM 0.34, but before that here's a final snapshot containing everything that will be in 0.34.

Changes:

  • Integrated current GNU Classpath cvs version.
  • .NET "generic class loaders" now return something (mildly) sensible when toString() is called on them.
  • ikvmc no longer warns about generic stubs.
  • ikvmstub now has WHIDBEY conditional code to properly determine if a class is a generic type instance (instead of the name based hack).
  • Fixed .NET generic type name mangling bug (nested generic types were double encoded).
  • Added support for loading .NET generic type stubs.
  • Fixed several .NET generic type loading bugs.
  • Fixed ikvm.runtime.Util.getInstanceTypeFromClass() to return null instead of throw an exception when it is called on a "dynamic only" class.
  • Changed ikvmstub to use java.util.zip instead of SharpZipLib.
  • Fixed index/length overflow detection in arraycopy_primitive_n methods.
  • Fixed JNI init args and thread attach string conversions.
  • Added workaround for .NET bug that caused OverflowException when compiling a class with an initialized final instance field of type char with a value > 32K.

Binaries available here: ikvmbin-0.33.2655.zip

Monday, 09 April 2007 10:19:22 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Monday, 26 March 2007
New Snapshot

The GNU Classpath 0.94 release is due soon (hopefully), but in the mean time here's a new snapshot.

Changes:

  • Integrated current GNU Classpath cvs version.
  • Fixed VMStackWalker.firstNonNullClassLoader() to handle reflection scenarios (this fixes a problem with serialization where the wrong class loader would be used when deserializing a class that has a custom readObject method.)
  • Added VMFile.setReadable/setWritable/setExecutable/canExecute. Although only setWritable does anything halfway usable (all these methods behave like the JDK on Windows, so only the file's ReadOnly attribute is manipulated).
  • Changed the build process to build IKVM.Runtime.dll in two passes, the first pass is used to compile IKVM.GNU.Classpath.dll against and then in the second pass IKVM.Runtime.dll can statically reference IKVM.GNU.Classpath.dll. This removes the need to use reflection to find IKVM.GNU.Classpath.dll at runtime and thus allows multiple versions of IKVM to co-exist side by side in the same AppDomain now.
  • Added support for stubbing abstract methods that contain unsupported argument types (ByRef and Pointer)
  • Regenerated mscorlib.jar and System.jar
  • Changed RetentionPolicy on .NET custom attribute annotations to RUNTIME, so that ikvmc sees them (fixes a regression).
  • Handled signature clashes in .NET type methods.
  • Made method parameter name handling robust against invalid or incomplete local variables tables.
  • Fixed interface implementation to recurse all the way up.
  • Fixed bytecode metadata table to mark div/rem bytecodes as possibly throwing an exception (this fixes bug 1676377, thanks to Dennis Ushakov for reporting this)
  • Made WinForms/AWT thread into a Background thread, to prevent it from keeping the process alive.
  • Added -time option to ikvmc.
  • Added x64 detection to jvm.dll build script.
  • Fixed several .NET 2.0 "ReflectionOnly" bugs.
  • Implemented java.awt.Desktop peer.
  • Fixed several issues pointed out by FxCop: FileChannelImpl now calls GetLastWin32Error() immediately after the P/Invoke. Runtime.addShutdownHook() now has a LinkDemand for ControlAppDomain (because it exposes the AppDomain.ProcessExit event, which also has this LinkDemand). Ghost types now have an Equals, GetHashCode, == and != method. Comparable.__Helper now has a private constructor and is sealed. Shadow methods in remapped types (that exist to hide the base class methods from Intellisense) now copy any LinkDemands from the methods they hide.

Binaries available here: ikvmbin-0.33.2641.zip

Monday, 26 March 2007 15:01:11 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Sunday, 25 March 2007
Running DOS Games

Since I'm running Vista x64, I can't run DOS apps anymore (since the AMD64 arch doesn't support VM86 when running in 64 bit mode). I can, of course, still run DOS inside the VMWare image of my old machine, but now there something much cooler JPC. An x86 PC emulator written in Java. Naturally, I had to try running it on IKVM:

Lemmings for DOS running on IKVM

The image shows Lemming for DOS running on the JPC x86 emulator running on IKVM.NET running on the x64 CLR.

Unfortunately IKVM's AWT support is not good enough for this app to work, so I had to do some pretty gross app specific hacks to make it "work" (that I obviously won't check in). It's also awfully slow (on JDK 1.6 the game is actually playable, but on IKVM definitely not.)

If any of the other GNU Classpath hackers want to try running JPC. Here's the AppletViewer class I used:

import java.awt.*;

class AppletViewer
{
  public static void main(String[] args)
  {
    Frame f = new Frame();
    f.setSize(640, 480);
    f.setLayout(new GridLayout(1, 1));
    org.jpc.j2se.JPCApplet applet = new org.jpc.j2se.JPCApplet();
    f.add(applet);
    f.show();
    applet.init();
    applet.start();
  }
}

The JPC applet jar can be downloaded here.

Sunday, 25 March 2007 12:41:43 (W. Europe Daylight Time, UTC+02:00)  #    Comments [2]
# Monday, 19 March 2007
ThinkPad Z61p & Vista x64

About a month ago my new ThinkPad Z61p arrived. It came pre-installed with Windows XP, but I always do a clean install to remove all the junk that comes with a new system (although Lenovo isn't nearly as bad as some OEMs). I decided to be adventurous and install Vista Ultimate x64.

Virtual PC 2007

I copied the harddisk of my old laptop to a VHD file, so that I would be able to use Virtual PC 2007 to run my old configuration. Well that was a big mistake. Virtual PC 2007 is a useless piece of crap. First of all, it had problems with the VHD file because it was bigger than 64GB (which surfaced as "Sector not found" errors in the virtual machine) and after I resolved that by shrinking the disk to 60GB the performance was horrible (it appears they *still* haven't solved the laptop/chipset/keyboard responsiveness issue). After getting fed up with that I switched to VMWare 6.0 beta and I have been very happy with that (I've been a VMWare user since 1.0, but wanted to give Virtual PC 2007 a chance since it's free [as in beer] now.)

Performance

The fact that the harddisk was *always* busy drove me crazy (and made things often very slow), so I've disabled the Windows Search indexing service, after doing that and using a 2GB Kingston USB memory key as a ReadyBoost cache performance is acceptable. It's hard to compare with my previous XP system, because I also switched to Office 2007 and Outlook 2007 is a real pig.

Problems

The integrated WiFi doesn't work. It looks like the driver works fine (I can see all WiFi networks in the area just fine), but when Vista tries to establish a secure connection, it fails (well, it actually succeeds and then breaks the connection again after a few seconds). All of the built in diagnostics crap is totally useless (as expected). The built-in flash reader also doesn't work (the Lenovo support site doesn't have a driver, but with some Googling I was able to find one, but it was very unstable).

IKVM

I've switched my main IKVM development environment to Visual Studio 2005 (but will still support .NET 1.1) and when I do my test builds I now build in 64 bit mode. This works surprisingly well and the performance is excellent. I was a bit skeptical about the x64 CLR JIT because of my previous experiences on Windows XP x64 (the performance there basically sucked), but the Vista CLR build (which is a newer build) appears to have fixed that.

As a result of running on .NET 2.0 most of the time now, I've fixed several "ReflectionOny" bugs (when IKVM is built on .NET 2.0 it uses the ReflectionOnly assembly loading context for ikvmc and ikvmstub).

Monday, 19 March 2007 08:52:40 (W. Europe Standard Time, UTC+01:00)  #    Comments [1]
# Saturday, 17 March 2007
More Magic

Thanks to Stuart's prodding, the next version of ikvmc will automatically add a System.IDisposable or System.Collections.IEnumerable implementation to any Java classes that implement java.io.Closeable or java.lang.Iterable (respectively).

That means that you can now do this in C#:

java.util.ArrayList list = new java.util.ArrayList();
list.add("foo");
list.add("bar");
using (java.io.FileWriter fw = new java.io.FileWriter("test.txt"))
{
  foreach (string s in list)
  {
    fw.write(s);
    fw.write("\n");
  }
}

Note that the interfaces are only added to the classes (i.e. the java.io.Closeable interface doesn't implement System.IDisposable). From Java this change is mostly invisible, e.g. when you use Java reflection you won't see System.IDisposable on java.io.FileWriter. However, when you use the instanceof operator or do a cast to cli.System.IDisposable, it will succeed. It would be possible to remove this inconsistency, but I don't think that's worth it.

Too Much Magic

Too much of anything is never a good thing, but in the case of adding magic to ikvm, it has always been very difficult to draw the line between just enough and too much. There already is a fair bit a magic in ikvm and I tend to be rather conservative in adding more. The main reason is that magic is almost never "perfect", this means that in most cases it will work as expected, but there are always edge cases where people will be surprised by how things work and that's clearly not good.

Stuart also wants Java's foreach construct to work on .NET types that implement IEnumerable, but to make that work would require turning java.lang.Iterable into a ghost interface and I currently feel that would be in the "too much magic" category, especially considering that ghost interfaces are not very good magic.

Saturday, 17 March 2007 15:05:07 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Friday, 16 March 2007
Microsoft dropping J# and JLCA in next version of Visual Studio

Via Lorenzo Barbieri (via Google blog search, I don't read Italian) I learned that Microsoft decided to drop support for J# and the Java Language Conversion Assistant in the next version of Visual Studio (code named Orcas).

I'm glad they finally realised the futility of competing with IKVM.NET ;-)

Friday, 16 March 2007 11:36:58 (W. Europe Standard Time, UTC+01:00)  #    Comments [3]
# Wednesday, 14 March 2007
DST Update

I made a new binary release of 0.32 that includes the back-ported GNU Classpath TimeZone fixes for the updates to the US DST rules.

Available here: ikvmbin-0.32.0.1.zip

Wednesday, 14 March 2007 15:51:01 (W. Europe Standard Time, UTC+01:00)  #    Comments [1]
# Friday, 09 February 2007
Class Loading Architecture

As I previously blogged, 0.32 has a new class loading architecture. I promised to explain the architecture, but I accidentally deleted the blog post I wrote about it a while ago and I didn't feel like rewriting it straight away, but I still need to do it, so here it is ;-)

The Basic Idea

Every .NET assembly has its own corresponding ClassLoader instance. This is true for assemblies generated with ikvmc as well as other .NET languages. The class loader instance corresponding to an assembly is known as the assembly class loader. It does not have a parent class loader (ClassLoader.getParent() returns null), but it does do a form of delegation. When the assembly class loader is used to load a class or resource, first it will search the corresponding assembly, if that doesn't result in the requested item, the assemblies directly referenced by the assembly are searched (and if that also doesn't find the item, the IKVM.GNU.Classpath assembly is searched).

The System Class Loader

By default the system class loader will be set to the assembly class loader of the main application executable assembly. If there is no main executable assembly (e.g. the main executable is unmanaged or the AppDomain was created without one) or the java.class.path or java.ext.dirs properties are set, then a URLClassLoader that searches the classpath is used. This means that in most scenarios no dynamic Java class loading is enabled by default. This also means that you don't have to worry about your application being affected by the CLASSPATH environment variable as set on the system where the application runs (which previously could -- and did -- result in hard to diagnose problems on some systems with a weird CLASSPATH setting.)

Dynamically Loading a Class

Class.forName() just works if the class loader it uses (and, like Java, it uses the class loader that loaded the calling class) can find the class. It can also be used to load classes from assemblies that are not referenced by any class loader that is already available. This is done by specifying the assembly qualified name of the type (in .NET form, without the cli prefix). Here's an example:

class MsgBox
{
  public static void main(String[] args) throws Exception
  {
    Class c = Class.forName("System.Windows.Forms.MessageBox, " +
                "System.Windows.Forms, " +
                "Version=1.0.5000.0, " +
                "Culture=neutral, " +
                "PublicKeyToken=b77a5c561934e089");
    c.getMethod("Show", String.class).invoke(null, "Hello, World!");
  }
}

Versioning

One nice benefit of the new architecture is that it is now possible for two (or more) different versions of a jar to be loaded and used in the same AppDomain. Previously that would sort of work, but it would break down if the code used Class.forName() or tried to load resources. However, now the class loader namespaces can be fully seperated (you still can't have a single assembly that directly references two versions of the same code, but indirectly it works fine.) Here's an example of an application that uses two different assemblies that both depend on different versions of the same assembly:

The rectangles represent assemblies and the ovals represent class loaders. The pink oval is the assembly class loader for App.exe and can see classes in both Foo.dll and Bar.dll, but won't be able to see any classes from either of the Widgets assemblies. The yellow oval is the assembly class loader of Foo.dll and it allows Foo.dll to see the correct version of Widgets.dll, but not the other one (nor any classes in App.exe, unless it uses the system class loader). Each Widgets.dll assembly will also have its own assembly class loader (not shown in the diagram) and that will only be able to load classes from the corresponding Widgets assembly.

JSR 277

The limitations of the Java class loading architecture have long been known and several hacks have been developed to work around some of those limitations, but it is clearly desirable (at least to some people) to replace the current architecture with something better. JSR 277 is trying to define that new architecture. I believe that the architecture that IKVM 0.32 introduced is very similar to what JSR 277 is going to end up like, so in the future it should be possible to support JSR 277 without any major changes. Also, if your Java code requires changes to be compatible with the IKVM architecture, it almost certainly will require similar changes to deal with JSR 277 and making these changes now will make it easier to migrate to JSR 277 based modules in the future.

Friday, 09 February 2007 09:27:03 (W. Europe Standard Time, UTC+01:00)  #    Comments [3]
# Monday, 05 February 2007
New Snapshot

It's been a while since the 0.32 release and there has been a fair bit of change going on, so I thought I'd release a snapshot for people who want to play with up to date binaries.

Changes:

  • Updated to current GNU Classpath cvs version.
  • Added support for representing .NET enum types as Java enums for use in annotations (.NET enum types now have an inner class __Enum).
  • Added support for adding fields to classes in map.xml.
  • Fixed remapping infrastructure to not generate superfluous method body for interface methods.
  • Added partial support for enum types in .NET attribute annotations.
  • Added Java 1.6 methods to java.lang.String.
  • Added -warnaserror option to ikvmc (suggested by David Ehrlich).
  • Many AWT improvements (by Volker Berlin).
  • Added caching to VMStackWalker.isHideFromJava to speed up stack walking (suggested by Trevor Bell).
  • Fixed handling of non-vector arrays.
  • Made JNIEnv.FatalError more compatible with JDK and removed call to JVM.CriticalFailure (which is reserved for IKVM bugs).
  • Centralised OEM string decoding in JNI code.
  • Changed JVM.CriticalFailure to write message to console instead of displaying a message box in ikvmc.
  • Fixed AnnotationBuilder to add ImplementsAttribute to annotation attribute, so that reflection correctly reports the implemented annotation interface.
  • Fixed AnnotationBuilder to ignore annotation attribute properties of type Annotation (as .NET attributes have no way to encode them).
  • Implemented annotation support in StubGenerator (used by ikvmstub and other code that reads statically compiled classes as resources).
  • Added warning to ikvmc when skipping a class that is already in a referenced assembly.
  • Changed ikvmc -nowarn to use only the first variable string in a warning as a key.
  • Changed ikvmc to fail with a Link Error when it detects a loader constraints violation (instead of emitting code that throws a LinkageError at runtime).
  • Fixed handling of bridge methods with covariant return types in ikvmc (to allow other .NET languages to call these methods [i.e. the non-bridge counterparts]).
  • Changed ikvmc to add EditorBrowsable(Never) attribute to bridge and synthetic methods.
  • Fixed workaround for Mono bug (lack of proper token support in reflection emit api) in field reflection support.
  • Fixed system property initialization to handle case where IKVM.GNU.Classpath doesn't have a Location (e.g. when it is loaded with Assembly.Load(byte[]) (suggested by Bill Seddon).

Binaries are available here. Source is available in cvs.

Monday, 05 February 2007 07:48:55 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]