Topic
  • 1 reply
  • Latest Post - ‏2008-07-10T18:55:57Z by brunocrt
SystemAdmin
SystemAdmin
235 Posts

Pinned topic Loading an unverified class

‏2007-10-25T20:21:08Z |
Hi,

First off, a little introduction, so I'm hopefully not considered heretic.

I'm the (sole) developer of a project called JauVM (http://jauvm.sf.net/). This project implements a JVM bytecode interpreter in Java, which allows interpreted JVM code to use both tail-calls and continuations. Some examples of this can be found in:
http://jauvm.svn.sf.net/viewvc/jauvm/trunk/jauvm/test/

Interpreted and "native" code can coexist and be freely mixed in one program. Methods tagged by the @interpretable annotation are interpreted by the JauVM, and all other methods are delegated to the underlying JVM (e.g.: Sun's; the JauVM is a Java program, that itself runs atop a JVM). For an example of this look at:
http://jauvm.svn.sf.net/viewvc/jauvm/trunk/jauvm/test/Pythag.java?view=markup

If you have any questions on the JauVM, feel free to ask. But now to the problem at hand.

The interpreter calls "native" methods using reflection, which works in all but one situation: non-virtual calls on the super instance. Static methods, interface methods, virtual methods all work. Constructors and private methods, also work (private methods thanks to setAccessible), and are non-virtual. It doesn't seem possible, however, to make the non-virtual call to a public/protected method, required to implement invokespecial on the super instance.

The only way I've been able to do this, is by generating a class at runtime, which is fine, except the verifier is quite strict, even on ACC_SUPER-less classes. For instance, the following two classes fail with "Illegal use of nonvirtual function call" and "Incompatible object argument for invokespecial", despite working flawlessly with "-noverify".




class superA 
{<br /> 

public 

static 

void call(A a);<br /> %load a<br /> invokespecial A.fn()void<br /> return<br /> 
}<br /> 
}<br /> <br /> 

class superA 

extends A 
{<br /> 

public 

static 

void call(A a);<br /> %load a<br /> invokespecial A.fn()void<br /> return<br /> 
}<br /> 
}


So, my question is, is it possible in any way to load specific classes at runtime bypassing the verifier? I understand this is a security issue, but so is (e.g.) accessing the Unsafe object, which you can do easily thanks to reflection and setAccessible (and my code already requires setAccessible to handle private members, as above). A non-portable solution (e.g., using Unsafe) would also help. I've tried Unsafe.defineClass, which seems to bypass some security checks, but not the verifier. Having the class be loaded by the null classloader seems to bypass verification, but then references to A above can't be resolved.

If you have any other ideas on how to implement this, that would be a great help too, obviously. JNI is always a possibility and I'm interested in a JNI solution, but even then I would still rather have a bytecoded option available alongside (even if unportable, unsafe).

Thank you all for your time and patience. If this is the wrong medium to ask such a question, I'm sorry. I'd still be glad if you could at least be so kind to point me in the right direction.

Regards,
Nuno Cruces
PS:
As a curiosity, the only other "similar" issue I've had implementing the JauVM is the need for unbalanced synchronization (which JVMs is allowed, but not required to accept). There, a combination of three implementations work to "solve" the problem: a pure Java version for those VMs that allow unbalanced syncronization; a Unsafe based version where available; a JNI version where available.
I have a working prototype of this, it still isn't available in the project page.
Thanks again!
Updated on 2008-07-10T18:55:57Z at 2008-07-10T18:55:57Z by brunocrt
  • brunocrt
    brunocrt
    1 Post

    Re: Loading an unverified class

    ‏2008-07-10T18:55:57Z  
    J2SE 5.0 adds a new feature to the Java platform which let you (among other things) specify class transformation agents to be used when executing a program.

    To use a transformation agent, you need to specify the agent class when you start the JVM. When using the java command to launch the JVM, you can specify agents using command line parameters of the form -javaagent:jarpath=options, where "jarpath" is the path to the JAR file containing the agent class, and "options" is a parameter string for the agent. The agent JAR file uses a special manifest attribute to specify the actual agent class, which must define a method public static void premain(String options, Instrumentation inst). This agent premain() method will be called before the application's main() method and is able to register an actual transformer with the passed-in java.lang.instrument.Instrumentation class instance.

    check the java.lang.instrument package.

    I believe this article can give you more clean examples about this feature:
    http://www.ibm.com/developerworks/java/library/j-cwt06075/index.html