# Friday, 25 January 2013
Fixing a Long Standing Limitation

I finally fixed the limitation that classes dynamically loaded by an assembly class loader can't access the internals of the assembly.

Here's a simple demonstration of the problem. Suppose you have these two classes:

class Other {
  static {
    Test.m();
  }
}

class Test {
  public static void main(String[] args) throws Exception {
    Class.forName("Other");
  }
  static void m() {
    System.out.println("Test.m");
  }
}

Now if you compile Test.class (without Other) into an assembly with a ClassPathAssemblyClassLoader and run this with IKVM.NET 7.2 you'll see something like this:


C:\j>ikvmc Test.class -classloader:ikvm.runtime.ClassPathAssemblyClassLoader
IKVM.NET Compiler version 7.2.4630.6
Copyright (C) 2002-2013 Jeroen Frijters
http://www.ikvm.net/

note IKVMC0001: Found main method in class "Test"
note IKVMC0002: Output file is "Test.exe"

C:\j>Test
Exception in thread "main" java.lang.ExceptionInInitializerError
        at cli.System.Runtime.CompilerServices.RuntimeHelpers._RunClassConstructor(Unknown Source)
        at IKVM.Internal.TypeWrapper.RunClassInit(Unknown Source)
        at IKVM.NativeCode.java.lang.Class.forName0(Unknown Source)
        at java.lang.Class.forName(Class.java:287)
        at Test.main(Test.java:9)
Caused by: cli.System.MethodAccessException: Test.m()
        at Other.<clinit>(Test.java)

The call from Other to Test fails with a MethodAccessException, because the dynamic assembly does not have access to the internal members of the Test.exe assembly.

Long ago I considered fixing this by adding an InternalsVisibleToAttribute to all statically compiled assemblies that allows the runtime generated dynamic assembly access to its internals, but I dismissed this because it would mean that untrusted code could abuse this same assembly identity to access the internals of any ikvmc compiled assemblies.

Forging a StrongNameKeyPair

Yesterday I realized that I could use InternalsVisibleToAttribute without opening a security hole. When the IKVM runtime is running as fully trusted code, it can forge a StrongNameKeyPair to attach to the dynamic assemblies it generates and thereby gain access to the statically compiled assemblies, without giving untrusted code the same access.

The only downside to this approach is that it relies on an implementation detail of the CLR (and Mono). I try to stay away from depending on implementation details, but in this case the gain far outways any risk.

Using It From C#

It also works for your C# assemblies. By adding a custom attribute, you can now enable dynamically loaded Java classes access to your assembly internals.

Here's a C# example:

using System;
using System.Runtime.CompilerServices;
using java.lang;
using java.lang.reflect;

[assembly: InternalsVisibleTo("DemoApp-ikvm-runtime-injected, PublicKey=00240000048000009400000006020000002400005253413100040000010001009D674F3D63B8D7A4C428BD7388341B025C71AA61C6224CD53A12C21330A3159D300051FE2EED154FE30D70673A079E4529D0FD78113DCA771DA8B0C1EF2F77B73651D55645B0A4294F0AF9BF7078432E13D0F46F951D712C2FCF02EB15552C0FE7817FC0AED58E0984F86661BF64D882F29B619899DD264041E7D4992548EB9E")]

interface IFoo {
  Program Instance { get; }
}

class Program : InvocationHandler {
  static void Main() {
    Class c = typeof(Program);
    var cl = c.getClassLoader();
    var interfaces = new Class[] { typeof(IFoo) };
    var handler = new Program();
    var proxy = (IFoo)Proxy.newProxyInstance(cl, interfaces, handler);
    Console.WriteLine(proxy.Instance);
  }
  public object invoke(object obj, Method m, object[] objarr) {
    return this;
  }
}

Here we create a Proxy for the non-public interface IFoo. This is allowed because of the InternalsVisibleToAttribute that gives access to an assembly named DemoApp-ikvm-runtime-injected with the specified public key. The name of the assembly must be the name of the current assembly (in this example "DemoApp") with "-ikvm-runtime-injected" appended. The public key is always the same. The corresponding private key does not exist.

Development Snapshot

Please note that this is a development snapshot, not a release or release candidate. So consider it untested.

Changes:

  • Use InternalsVisibleToAttribute to allow the runtime to dynamically inject classes into statically compiled assemblies.
  • Stop generating proxy helpers for non-public interfaces.
  • Added support for RadialGradientPaint in Graphics.setPaint().

Binaries available here: ikvmbin-7.3.4772.zip

Friday, 25 January 2013 07:51:20 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Wednesday, 16 January 2013
New Development Snapshot

The recent Windows RT jailbreak enabled me to run IKVM on my Surface RT. Out of curiousity I decided to run a part of the test suite. Only three tests failed, one because it relies on specific GC behavior and two because they use JVM.DLL. Previously, IKVM's JVM.DLL assemblies were created with ilasm, because that was the easiest way to create unmanaged exports at the time. However, ilasm doesn't seem to support ARM, so I added this support to IKVM.Reflection and wrote a simple tool to generate unmanaged export assemblies. Of course, supporting unmanaged exports on Windows RT in IKVM.Reflection is not very useful, but it was an interesting exercise to learn a little bit about the ARM instruction set.

I also did some more useful work. I finally got around to changing how ikvmc handles assembly references. It now works like the C# compiler and uses the IKVM.Reflection support for missing assemblies that I added for mcs. This means that it no longer automatically loads assemblies (apart from the IKVM runtime and class library assemblies) and you need to add explicit references for indirectly used assemblies as well. The downside is that this has the potential to break some builds, but the upside is that the compilation process is now more predictable and only loads the actually required assemblies, like a "real" compiler, instead of the System.Reflection heritage that required loading even unused dependencies.

Another change is that ikvmstub jars are now officially deprecated from being used with ikvmc (it will still work for a while, but a warning message is issued).

Finally, it is now illegal to explicitly reference a secondary assembly in a shared class loader group. Previously this caused a warning message, but now this is an error. You need to reference the primary assembly.

Changes:

  • Deduplicate ikvmc messages based on all parameter values, not just the first one.
  • Allow ikvmc messages to be suppressed based on any number of parameter values.
  • Fixed ikvmc to write fully specific -nowarn options to suppress file.
  • Fixed ikvmc to handle missing types.
  • Added ikvmc support for missing assemblies.
  • Officially deprecated using stubs with ikvmc.
  • Bug fix. Don't add duplicate methods to attribute annotation interfaces. The primary cause of this was attributes with virtual properties where we would add the base class property as well as the derived class overridden property.
  • Changed build process to replace ilasm usage to generate JVM.DLL with a custom tool.
  • Bug fix. Local variable analysis for finally blocks was incorrect. Fixes bug #3600788.
  • Changed ikvmc to give an error message (instead of a warning) when referencing a secondary assembly from a shared class loader group).
  • Made ikvmc EditorBrowsableAttribute construction fully symbolic, to avoid having to load System.dll.
  • Disabled automatic assembly loading for ikvmc.
  • Suppress ikvmc warnings after an error has occurred (to avoid obscuring the fact that compilation failed).
  • IKVM.Reflection: Added UniverseOptions.ResolveMissingMembers and deprecated EnableMissingMemberResolution().
  • IKVM.Reflection: Added Universe.ResolvedMissingMember event.
  • IKVM.Reflection: Fixed importing of CLR types with funny names (where we'd previously run into bugs in CLR's Type.Name and Type.Namespace).
  • IKVM.Reflection: Restructured relocation writing to pack all relocation in a page in the same block, as WoA apparently requires this.
  • IKVM.Reflection: Implemented ARM startup stub.
  • IKVM.Reflection: Implemented ARM unmanaged exports.

Binaries available here: ikvmbin-7.3.4764.zip

Wednesday, 16 January 2013 12:24:57 (W. Europe Standard Time, UTC+01:00)  #    Comments [1]
# Tuesday, 15 January 2013
IKVM.NET 7.2 Update 1 Release Candidate 0

An updated release with a couple of bug fixes.

Changes (relative to 7.2):

  • Bug fix. Don't deadlock AppDomain.ProcessExit event handler when the event gets called from another thread than the one initiating exit.
  • Bug fix. Static compiler should not use proxy stubs to implement non-public interfaces in another assembly.
  • Bug fix. Don't add duplicate methods to attribute annotation interfaces.
  • Bug fix. Local variable analysis for finally blocks was incorrect. Fixes bug #3600788.

Binaries available here: ikvmbin-7.2.4630.6.zip

Sources: ikvmsrc-7.2.4630.6.zip, openjdk-7u6-b24-stripped.zip 

Tuesday, 15 January 2013 11:47:09 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Sunday, 06 January 2013
New Development Snapshot

I've been busy with other stuff, but I did manage to fix a couple of bugs and add a new feature. So a new development snapshot.

Changes:

  • .NET resources in non-Java assemblies are now exposed as Java resources.
  • Added IKVM.Attributes.JavaResourceAttribute to publish .NET resource to Java under a different name.
  • Bug fix. Don't deadlock AppDomain.ProcessExit event handler when the event gets called from another thread than the one initiating exit.
  • Minor optimization. Only register the AppDomain.ProcessExit event handler when necessary.
  • Bug fix. Private methods declared in map.xml should not be made virtual.
  • Support "attributes" attribute on method tag in map.xml for methods declared in remapped types.
  • Recognize methods in remapped types with the "__<" name prefix as HideFromJava.
  • Bug fix. Static compiler should not use proxy stubs to implement non-public interfaces in another assembly.
  • IKVM.Reflection: Implemented __ContainsMissingType for function pointer types.
  • IKVM.Reflection: Changed __ContainsMissingType to take custom modifiers into account.
  • IKVM.Reflection: Added caching for __ContainsMissingType property to simplify the prevention of infinite recursion while evaluating generic parameter constraints.

Binaries available here: ikvmbin-7.3.4754.zip

Sunday, 06 January 2013 09:51:23 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]