Review Request: 8001533: Java launcher must launch JavaFX applications
Kevin Rushforth
kevin.rushforth at oracle.com
Sat Nov 17 00:05:09 UTC 2012
Hi Dave,
I hadn't yet given much thought to retiring the JavaFX-Application-Class
attribute, but I agree that it could be considered legacy if we do make
the change to the javafxpackager to drop it.
I just talked with Mandy about a couple of launcher questions that she
had relating to the main class. During the course of answering her
questions, a couple of other questions and thoughts came up regarding
launching via the Main-Class versus the JavaFX-Main-Class if both are
present. I wanted to discuss these before I provide my feedback on the
webrev itself.
There are three primary scenarios to consider when executing an
application from a jar file. I put the most interesting one first:
1) An existing JavaFX application, packaged either using the
javafxpackager tool or the underlying <jf:jar> task from javafx-ant.jar,
which is used by the packager. The jar file produced by the current
version of this tool will always have both of the following entries in
its MANIFEST:
JavaFX-Application-Class: mypkg.MyApp
Main-Class: com/javafx/main/Main
where "mypkg.MyApp" is the actual name of a public class that extends
"javafx.application.Application". The packager inserts the
"com/javafx/main/Main.class" file into the jar file. That class does not
exists in the JavaFX runtime jar file, jfxrt.jar (which is currently in
JRE/lib and is moving to JRE/lib/ext).
When this jar file is launched today with "java -jar myjar.jar" the java
launcher does the usual thing with this jar file and calls the
main(String[]) method of the com.javafx.main.Main class, which will do
the following:
A) Locate the javafx runtime and construct a URLClassLoader with that
jar and the deploy jars on the classpath. Locating the JavaFX runtime
jar is no longer necessary, but adding the deploy.jar is still needed
unless we want to regress from current behavior. As an aside, Mandy
found a potential bug by code inspection in the way the JavaFX main
launcher class constructs the class loader -- it uses "null" as the
parent rather than ClassLoader.getSystemClassLoader(), which may be the
root cause of RT-20988 <http://javafx-jira.kenai.com/browse/RT-20988>.
B) Read the manifest for the JavaFX-Main-Class, the
JavaFX-Preloader-Class, and the JavaFX-Class-Path (which the
javafxpackager supports to allow a developer to specify additional
dependent jar files).
C) Sets up a network proxy unless the JavaFX-Feature-Proxy manifest
entry is set to something other than "auto" (auto is the default).
D) Call into the platform LauncherImpl.launchApplication method,
passing in the application class, the preloader class (if specified in
the jar manifest), and the command line arguments.
So here is the dilemma. When coming up with the requirements for the
launcher, we had defined that the JavaFX-Application-Class should be
called in this case for existing FX applications, taking precedence over
the Main-Class. I still believe that is the best choice, but it isn't
without drawbacks (see below). If the new JDK8 java launcher were to
call into the main method of the class specified by Main-Class, ignoring
the JavaFX-Main-Class, then we would not get any benefit out of the new
launcher for existing applications. The main method of the FX Main
launcher class included in the jar will use whatever the current
mechanism is for locating the JavaFX classes, which seems undesirable
since it adds those jars to a new URLClassLoader that it creates rather
than just using the existing class loader. Further, we would be stuck
with any bugs that we might find in that old, "statically linked" Main
FX launcher, such as the bug that Mandy found.
However, while we no longer need or want the "locate jfxrt.jar and add
it to the classpath" part of what the existing Main class does, it does
do a couple other things that are useful. If the new java launcher calls
directly into the JavaFX runtime LauncherImpl.launchApplication method,
bypassing the main method of the packaged Main class, we will have no
good way -- and probably not enough information -- to know whether or
not to set up the proxy configuration and add additional jars onto the
classpath (deploy.jar and any jar files specified by JavaFX-Class-Path
at a minimum). Currently you don't support the JavaFX-Preloader-Class
either, but that is more easily solvable.
Either way, it seems like we will have some compatibility issues and
functionality concerns. I think this is solvable, perhaps by defining a
new variant of LauncherImpl.launchApplication that accepts more
arguments (like a map of the manifest entries), but I wanted to raise
the issue.
The other two cases are much easier:
2) A Java application using some JavaFX that is packaged by just jar-ing
up the class files and setting a main class via the "Main-Class" jar
attribute in the MANIFEST, and without a "JavaFX-Main-Class" aattribute.
Running "java -jar myapp.jar" will just launch an run the app by calling
into the "public static void main(String[])" method.
With the modified JDK8 launcher, the only question is this: if the
specified Main-Class both extends javafx.application.Application *and*
has a main method, which one should take precedence? I can see arguments
for either one. For consistency with applets and webstart applications,
it seems that launching it as an FX application will provide the most
consistent experience. This is what your webrev will do which seems good.
Note that the same concern about lack of support for
JavaFX-Preloader-Class, etc, exists in this case as in scenario #1.
3) A JavaFX application, packaged manually or by a modified version of
the JavaFX packager, without a Main-Class (no such modification has been
specified, but could be considered once the java launcher is modified to
recognize JavaFX classes as an alternative to dropping
JavaFX-Application-Class and just using the MainClass). In this example,
the MANIFEST of the jar file would have the JavaFX-Application-Class to
specify the subclass of javafx.application.Application that should be
launched. If this case is supported, it would be simple and would do
what we want, but might not actually occur depending on other decisions
that are made.
Mandy can chime in with her thoughts on this, but it seems that we need
to answer the questions in scenario #1 before proceeding. Do you think
it might be better to wait until these can be resolved even it means
missing M5 (the move of jfxrt.jar to lib/ext won't happen for M5
anyway...it is scheduled for M6)? Or do you think they can be resolved
with minor changes to the existing functionality?
-- Kevin
David DeHaven wrote:
>>> I cleaned it up quite a bit, I think it looks a lot better now:
>>> http://cr.openjdk.java.net/~ddehaven/8001533/webrev.1/
>>>
>>> The comments still need some attention, I'll get that first thing on the morrow.
>>>
>>> -DrD-
>>>
>>>
>> I haven't done a detailed code review but I'm wondering about preferring JavaFX-Application-Class over Main-Class. I realize there may be some history here, perhaps with the javafxpackager tool, but I'm just concerned that the JAR File specification specifies the Main-Class attribute, now it will be usurped and ignored if this custom attribute is present.
>>
>
> JavaFX-Application-Class is for backwards compatibility with existing applications, my understanding is it's being deprecated. Moving forward JavaFX applications will only use Main-Class. Kevin can correct me if I'm wrong :)
>
> Am I wrong in thinking there should be no impact on profile support if it's being deprecated?
>
> -DrD-
>
>
More information about the core-libs-dev
mailing list