Loading applet with custom class loader
Hey,
My problem is a little complicated. I'll try to explain in details - but pls do not hesitate and ask for clarifications...
I have a product - applet based. I want to manipulate the code on run-time using aspectj. Since the applet is running on the client jvm I can't load it with '-Djava.system.class.loader=org.aspectj.weaver.loadtime.WeavingURLClassLoader' as with applications.
My current solution is to 'replace' the applet tag in the jsp - to call a wrapper applet. The wrapper applet is initiate the product with the aspectj classloader:
URL source = new URL("jar:"+getCodeBase()+"aProduct.jar!/");
URL aspect = new URL("jar:"+getCodeBase()+"myAspects.jar!/");
URL[] urlList = {source, aspect };
URL[] aspectsList = {aspect };
WeavingURLClassLoader weavingClassLoader = new WeavingURLClassLoader(urlList, aspectsList,
Thread.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(weavingClassLoader);
Class mainApplet = weavingClassLoader.loadClass("com.company.product.ProductApplet");
Object applet = mainApplet.newInstance();
if (mainApplet != null) {
Class[] stubArgs = {AppletStub.class};
Method setStub = mainApplet.getMethod("setStub", stubArgs);
Object[] stubObjects = {new MyAppletStub(this)};
setStub.invoke(applet, stubObjects);
Class[] args = null;
Method init = mainApplet.getMethod("init", args);
init.invoke(applet, (Object[])null);
this.add((Component)applet);
}
The product applet is trying to get info from the browser and to interact with java script - but it lost its 'connection' to the browser when I loaded it and add it to the wrapper applet. This is why I'm setting the applet stub - so whenever someone is calling 'getParameter', getJSObject or getAppletContext - it's getting my wrapper 'getParameter', getJSObject or getAppletContext. - this is working great!
the current status is that the product is having some controllers for the GUI that have one instance for each applet on the browser (there are cases that some applets are running on the same page). The product is using:
JOptionPane.getFrameForComponent(component) - (where the component is the applet)
in order to select between the controllers.
I'm running in debug mode and getting the same controller for the product applet - but in some cases (still for the same applet) I'm getting another controller (it trys to get the parent frame - that is my wrapper applet frame) - this is causing eventually to a null pointer.
Since we have a decision - not to touch the product code and to be generic to all products - I need to find a way to solve this out.
another option is trying the 'new java plugin' - 6. they added an option to load applet using jnlp (as in webstart). You can load the applet with jvm arguments. But I'm not sure that loading it with:
java.system.class.loader=org.aspectj.weaver.loadtime.WeavingURLClassLoader
will pass the security restrictions
Any thought/suggestion will be more then welcome

Comments
I don't think your "playing" with class-loaders really works.
Web browsers use only one class loader - the one created when the application starts.
read this.
it's working
on a simple sample (ha ha) I managed to replace string on a label on an applet
I have a wrapper applet that loads the main applet with the WeavingURLClassLoader that gets the products url and the aspects url as parameters
Cool!
What's next?
it was a long story to read - right?
I'll try to make it short:
Important thing - I'm overriding the original applet - appletStub & appletContext so whenever someone refers to the original appletStub/Context its getting my wrapper applet appletStub/Context - this way the 'communication' with the browser is not lost
But I still have problems with:
When the original code is trying to get the applet's frame with:
JOptionPane.getFrameForComponent(originalApplet)
I'm getting the parent frame (my wrapper applet frame) since the original applet has no frame attached
look what I found:
https://jdk6.dev.java.net/plugin2/jnlp/#COMMAND_LINE_ARGS
I can pass the -Djava.system.class.loader=org.aspectj.weaver.loadtime.WeavingURLClassLoader to the JVM
"A set of "secure" JVM command-line arguments and system properties is defined in the JNLP File Syntax section of the Java Web Start Developers' Guide. In the new Java Plug-In, by default, only these secure command-line arguments may be specified on a per-applet basis.
Non-secure command-line arguments may only be specified on a per-applet basis if:
* the applet is launched via a JNLP file, and
* the command-line arguments are specified in the JNLP file, and
* the applet's JNLP file is signed. "
But - how the hell can I sign a jnlp file???
I think what they mean is that the jar file pointed by the jnlp must be signed
good morning
r u familiar whith the pack200? - I think this is how I can sign the jnlp file
http://forums.java.net/jive/thread.jspa?threadID=42760&tstart=60
No I'm not.
Anyway, I think I asked you before - Why are you using LTW.
If you instrument the bytecode during compile time you won't have these problems...
I'm trying to pack the jnlp inside the signed jar.
About the Loadtime vs Compiletime - "It's beyond my control"
Hi Keren,
I also try to replace the ClassLoader from the IE plugin. I tryed to add the
-Djava.system.class.loader=CustomClassLoader
in the Java Control Panel but it doesn't seem to load this class loader.
I tried to put it in the same directory like the applet itself and also localy in the CLASSPATH, but no look.
There doesn't seem to be any documentation for how to do this.
How did you get around this problem?
Thank you
Peter
well... loading an applet with your classloader is a tricky thing... you cannot really 'touch' the loaded VM on the client machine...
The way we tried to handle it was to create a wrapper applet that will initiate our classloader and then load the original applet and place it's main panel on the wrapper applet. This way all your applet classes will be loaded with your classloader.
But, we found some problems along the way... it depends how complicated your applet is. If the applet should be communicated with the html page or with another applet on the same page you are loosing the parent(page)-applet communication channel...
As Adi suggested, why aren't you using dynamic byte-code instrumentation during compile or post compile time (with ASM/BCEL/janino etc.)
:)
we are ;)
but that was not the question of Peter...
I got it working by creating a modified sun.applet.AppletClassLoader, put it in a jar and added the jar at the beginning of the boot class path using
-Xbootclasspath/p:C:/<path>/cl.jar
in the applet configuration panel. May be this can save someone some time.
Thanks for your help.
Peter