A technical Matryoska doll – Java inside .NET

Google Closure Compiler in .NET via IKVM

The Google Closure Compiler is a great tool for minifying JavaScript – it has the ability to both minify and optimize code, with output that’s both lightweight and performant. If you’re living on the .NET stack though, the fact that it’s in Java might be an impediment to either use or integration.

In this post I’m going to go through the basics of using IKVM to cross-compile the Java libraries to .NET and allow the closure compiler to run on the .NET platform.

If you haven’t come across IKVM before, the short description is that it’s a platform bridge for Java to .NET. It translates Java byte code to MSIL, and provides a .NET compiled version of the OpenJDK runtime. You can find out more on the website – in short, it’s amazing.

There are two ways to roll with this. IKVM supports a both dynamic mode, where jars or classes are cross-compiled at runtime; and a static mode, where a compiler produces a DLL or EXE from the jars or classes. In the static case, the resulting DLL can then be used from other .NET code to integrate Java APIs into .NET applications.

Getting started

First thing’s first: download IKVM and the closure compiler jar. You will also need the json.jar library that can be found in the closure compiler source. (Note that none of the following requires a JRE or JDK for this to work – just the .NET runtime, version 2 and above.)

Extract IKVM and the closure compiler to separate folders on your disk, placing the json.jar file in the same folder as compiler.jar.

Running in dynamic mode

This is the simplest method of execution, as the ikvm executable works the same way that the JRE does. Open a command line in the folder where the closure compiler jar resides and execute:

[path-to-ikvm]\bin\ikvm -jar compiler.jar --js=[source-javascript] --js_output_file=[destination-javascript-file]

This will run the compiler and output the result to the specified location.

While this mode is simple, you will have noticed that it’s slow to run – it took about 15s on my system compared with less than 5s using the JRE. This penalty comes from the fact that IKVM needs to cross-compile the jar before it runs – let’s speed it up.

Static compilation

For this section, we’ll compile the compiler.jar to compiler.exe – a Windows executable that runs on the .NET runtime.

From the command line, execute the following:

[path to ikvm]\bin\ikvmc -out:compiler.exe json.jar compiler.jar

Note that we’re using ikvmc (the compiler) here, not ikvm (the runtime). The above command instructs the IKVM compiler to compile the two jars into a single executable, and put the result into compiler.exe.

Why json.jar? Good question. This jar is a static dependency of the closure compiler, though I’m not sure where it’s  used (by the closure compiler). Adding it to the command line in this way means that it is compiled into the same executable as as the closure compiler, making the resulting executable easier to handle.  It is possible to compile the json.jar separately, then reference the resulting DLL when compiling closure.jar:

[path to ikvm]\bin\ikvmc -out:json.dll json.jar
[path to ikvm]\bin\ikvmc -out:compiler.exe -reference:json.dll compiler.jar

Not rocket science – you’ll notice the json.dll is also output in the current folder, and that the compiler.exe decreases in size.

Now if you’ve executed the above commands, you will have noticed that a number of warnings are output by the compiler, for example:

Warning IKVMC0100: class "org.apache.xmlbeans.XmlCursor$TokenType" not found
Warning IKVMC0100: class "org.apache.xmlbeans.XmlCursor" not found
Warning IKVMC0111: emitted java.lang.NoClassDefFoundError in "com.google.javascript.jscomp.mozilla.rhino.xml.impl.xmlbeans.LogicalEquality.nodesEqual(Lorg.apache.xmlbeans.XmlCursor;Lorg.apache.xmlbeans.XmlCursor;)Z"    ("org.apache.xmlbeans.XmlCursor")

What you’re being warned about here is an unresolved dependency in the compiler.jar. The Rhino JavaScript interpreter, which is included by the closure compiler has a dependency on the Apache XML Beans project. This isn’t used by the closure compiler AFAIK, so it can be ignored. You could, however, get the XML beans project and start compiling that (and all its dependencies) but in this case it’s not worth it. The same goes for the ANT dependency that is also shown in the warnings. The closure compiler doesn’t use these bits so you can ignore it.

Running compiler.exe

Now you have the executable, but when it runs it will crash – why? Merely that the executable needs some IKVM DLLs present to find the core library parts. These are all present in the IKVM bin folder. The selection of these that we need is:

  • IKVM.OpenJDK.Core.dll
  • IKVM.OpenJDK.SwingAWT.dll
  • IKVM.OpenJDK.Text.dll
  • IKVM.OpenJDK.Util.dll
  • IKVM.OpenJDK.XML.API.dll
  • IKVM.Runtime.dll

The dependency list can be found by inspecting the executable for its library references, saving you from needing to copy the entire set of IKVM library DLLs.

Copy the above list from the IKVM bin folder to be alongside compiler.exe. You can now run “compiler -?” without issue.

Of course, compiling JavaScript is also on the cards:

compiler --js=[source-javascript] --js_output_file=[destination-javascript-file]

There’s no explicit use of  IKVM here – all that’s used are the runtime DLLs. If you look at the decompiled version of the code you’ll see that there’s very little extra weight added by IKVM, and some of that (the line number symbols) is optional.

Speed

Running a test on the JQuery source code on my machines resulted in the following results.

JRE 7s
IKVM 16s
Compiled 8s

As you can see, while the runtime compilation option is expensive, the compiled .NET code runs at a comparable speed to its ‘native’ JRE counterpart. Jeroen Frijters has done an amazing job to get IKVM performing as it does.

This is just the start of what is possible – the real reason I wanted to look at the Closure Compiler is to see about integrating it with the Client Dependency Framework – a filter that enables minification and bundling via an ASP.NET handler. More on that to come…


Use build configurations to control Razor compilation

Recently Phil Haack posted an article on “Compiling MVC Views In A Build Environment”, describing how to switch on view compilation. This can be incredibly useful, surfacing compilation errors across the project rather than relying on picking it up at runtime. However, I found that it slows compilation down quite significantly. It also seems to


ASP.NET MVC error: “The value ‘x’ is not valid for Id”

In my current project I’m using ASP.NET MVC 3 and enjoying it; kudos to Mr Haack and his minions. That said, I just had a problem that took me ages to sort out, though it is trivially simple in retrospect. I kept getting a ModelState error that ‘The value “x” is not a valid value


Output inserted values instead of scope_identity()

In the faint hope that I’ll remember this instead of doing it the hard way… When inserting rows into a table that has calculated rows (in particular an identity column), it is possible for SQL Server to output a selection of the inserted values into a table variable. This is useful if the value of


Override templates in an ASP.NET MVC project

The built-in templates for ASP.NET MVC get you up and running quickly; but as you build a project it’s more productive to have it generate output that fits with your requirements, rather than the generic output that will need to be changed each time. Thankfully, this is easily accomplished by copying the default templates into


Creating an Umbraco custom section

I needed to create a custom section for a project I am working on, which isn’t well covered in documentation, however the Umbraco community has stepped up and published some excellent guides for getting this done. Below are some links to these high quality articles, and some additional notes.


ASP.NET sites not working

I wasted a few hours tracking down an issue the other day where I couldn’t get an ASP.NET website running on a fresh install of Windows 7 and VS 2010. This website was running on my previous install, making it very frustrating. I spent a lot of time running through event log red herrings before


Sorting with LINQ: don’t use anonymous types

I got the error message “System.ArgumentException: At least one object must implement IComparable.” today for the following, seemingly innocuous code. var ordered = order.Lines.OrderBy(l => new { l.AdminCode, l.OrderLineNr}); I thought this was the way to do it; after, that’s the way that you use Join() for multiple properties. What it was however was a


Using asymmetric properties in views

Many people separate their business logic and view classes into two or more separate assemblies. This gives rise to the ability to use an asymmetric set for view properties that aren’t meant to be accessible. Simply put: public string SomeProperty { get; internal set; } The internal modifier means that this property is only accessible


Google Docs API: get all spreadsheets/docs in a folder

It’s easy enough to get a list of spreadsheets for a user, or a list of folders, but there’s a trick to getting the contents of a folder. The first part of the trick is to ignore the category. Firstly, because it’s removed in version 3.0 of the API, and secondly because it filters by