Question

I'd like to be able to generate and load custom classes within an (unsigned) applet. Generating them I can deal with, but I'm battling with the applet SecurityManager that doesn't seem to want me to load them.

Here's a visual overview; as you can see I'm stuck on Phase 2:

underpants gnomes

What I originally intended was to use a custom class loader. Apparently this isn't allowed in an applet; the ClassLoader constructor throws a SecurityException.

Then I considered calling ClassLoader.defineClass(String name, byte[] b, int off, int len) on another class loader directly, but that method is protected.

I tried to make the method accessible via reflection. My hopes there weren't high but I tried it and indeed that too threw a SecurityException.

URLClassLoader appeared to offer salvation: it has a static factory creation method which does not throw any security exception. However, that technique doesn't permit subclassing the loader or access to the protected defineClass method. It only accepts an array of URL objects.

So I tried to subclass URL to override its openConnection method to return my class bytes that way, but the URL class is final.

Then I tried creating a custom URLStreamHandler with an overridden openConnection method and passing it to the constructor of a URL. The SecurityManager threw another fit over this.

So then I tried calling URL.setStreamHandlerFactory with a custom factory that would return my custom stream handler. There was the SecurityManager again, complaining, because what else is it good for if not complaining?

So then I tried creating a javax.management.loading.MLet. I have no clue what it's for but it's a subclass of URLClassLoader that allows specifying a custom URLStreamHandlerFactory in its constructor and doesn't mention throwing a security exception, but it still did anyway.

In desperation I tried calling ProxySelector.setDefault with a custom ProxySelector, hoping to incercept a URL and somehow route it back into my applet, but I don't have permission for that either.

I tried setting the java.system.class.loader property via a <param name="java_arguments" ...> tag, but it didn't seem to be one of the honored properties.

Finally, the only remaining way I can think of to do this is to send my class bytes up to a remote server that will generate a temporary URL that I can use in conjunction with URLClassLoader.newInstance(URL[]). That would work but I really don't like the idea. It seems like it could get complicated fast, with the interaction of the different ClassLoaders, and the server-dependence is not really practical for what I want to do. Apparently the SecurityManager is only too happy to let you create a URLClassLoader, but gets spontaneously upset when you try to use it.

I would like to do this from within the normal unsigned applet security sandbox if it's at all possible, so that the experience is seamless.

But mostly I'm just baffled, because if it's not possible it makes no sense. If the SecurityManager is happy about loading classes from arbitrary external URLs it shouldn't mind loading one from a byte array in a local variable. The restriction is still nonsensical. The code is still internal and sandboxed.

It's useful both for dynamic code generation and for implementing custom JAR compression, like LZMA compression.

Help!

Was it helpful?

Solution

..the SecurityManager again, complaining, because what else is it good for if not complaining?

It is there for the protection of the end user, against doing exactly the sorts of things you are attempting.

..how do I load the class?

Sign the Jar, get the user to accept the digitally signed code.

..send my class bytes up to a remote server that will generate a temporary URL that I can use in conjunction with URLClassLoader.newInstance(URL[]).

A sand-boxed applet cannot create an URLClassLoader.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top