arch@glassfish.java.net

Re: [arch] Some follow-up proposals and questions after the app client container review

From: Bill Shannon <bill.shannon_at_sun.com>
Date: Sat, 21 Feb 2009 18:11:44 -0800

Finally returning to this (much too long) message. Am I the only other
person who cares about this?

Tim Quinn wrote:
> I was hoping to avoid wrapping all the JARs into an umbrella JAR, partly
> to streamline deployment. Also, to take best advantage of Java Web
> Start's caching we would need to serve the individual JARs separately.

Yes, you need to keep the jars separate on the server for Java Web Start,
but that doesn't mean you can't bundle them into one jar for the app
client case.

> If we used this open source technology to create an
> umbrella JAR then that means more differences in the ACC code path for
> the JWS vs. the non-JWS case.

Yes, that's true.

> Also, I looked into this general idea a while ago. The comments in
> forums from Java engineers at that time was that writing a class loader
> to handle JARs within JARs was certainly possible but could be very slow
> if the umbrella JAR were not expanded into a temp directory and the
> class path set to the various expanded JARs.

It's probably worth a day to find the technology and give it a try.
(I really wish I could remember the name of it...)

> I have a simple way for the appclient script to map its arguments to a
> "java" command that's very similar to what a user could have used
> manually to accomplish the same launch. That has the advantage for us,
> selfishly, of supporting not two ways to launch app clients but really
> just one without making it cumbersome for the "appclient" script user.
> And this brings me back to the question of what we would put in the
> Main-Class manifest entry of the appclient1.jar we would generate.
> Right now, I am thinking that we'd specify the main class of the app
> client and not main class of the ACC, and rely on an ACC Java agent to
> do some very mild byte code transformation. Please read on before
> panicking!

The agent approach is easier for us when it's hidden in the appclient
command, but it's harder (and scarier) for people who want to run the
app client themselves.

> Of course if we specify the app client's main class as the Main-Class in
> the generated manifest then the ACC needs some other way to gain control
> before the developer's main class runs. The Java agent would register
> a class transformer with the VM that would insert logic into the static
> initializer of the developer's main class (and no other class). This
> logic would simply invoke a static method on the ACC which would
> initialize the ACC (including injection into the now-loaded main class.
> The spec requires that any injection occur before the developer's main
> method is invoked, and this design would meet that requirement. Then
> the rest of the developer's static initializer (if any) would run,
> followed by the VM's invocation of the main method of the developer's
> now-injected main class.

I'd sure prefer to avoid byte code transformations.

> So how does the agent know which is the one class to transform? In the
> "appclient" case, the script can provide all the user-provided
> command-line arguments as agent arguments, so the agent can
> unambiguously determine which is the main class from those arguments.
> For the "java" case ... Well, despite discussing this with several VM
> people a long time ago and very recently, there is no supported,
> standard way for a Java app or even an agent to find out what main class
> the launcher has chosen to run. So that's why we'd ask the user
> entering the "java" command to tell us, via an agent argument, the main
> class or the JAR which contains it. This is redundant with what he or
> she would already be entering on the "java" command but there seems to
> be no way to avoid this. I've filed an RFE against the
> agent/instrumentation module of Java asking for a way to get the main
> class. If this feature ever arrives then we could take advantage of it
> and relax this requirement on our "java" command users at that point.

Wouldn't it be simpler to just create your own app client container main
class, have java run that, and have that run the app client? You know
the app client main class by reading the Class-Path header.