Review Request: 8001533: Java launcher must launch JavaFX applications (original) (raw)
Kevin Rushforth kevin.rushforth at oracle.com
Sat Nov 17 00:05:09 UTC 2012
- Previous message: Review Request: 8001533: Java launcher must launch JavaFX applications
- Next message: Review Request: 8001533: Java launcher must launch JavaFX applications
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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:
- 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:
- 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.
- 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-
- Previous message: Review Request: 8001533: Java launcher must launch JavaFX applications
- Next message: Review Request: 8001533: Java launcher must launch JavaFX applications
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]