Just in case you had not though of this (I expect you have), but you can have a 
kind of static gateway boolean preventing toolkit being created as long as it 
should not be.

java -Djavafx.toolkit.noSingleton

public static synchronized Toolkit getToolkit() {
    if (TOOLKIT == null && System.getPropery("javafx.toolkit.noSingleton") != 
null) {
        return null;
    }
    // existing code goes here....
}

And then when it is ok...
System.clearProperty("javafx.toolkit.noSingleton")

Or, if you have a good place to call a "setNoSingleton(true)" or the other way 
around, prior to the first getPlatform, use a static boolean (better performance).

Of course the returning-null scenario's need to be handled on severfal places, 
or some kind of stub should be returned.




On 4-5-2018 00:03, Kevin Rushforth wrote:
Hi Johan,

I don't know whether this work at all, and it might be even more work than what you are 
proposing, but a possible approach would be to create a variant of the getToolkit method 
with a boolean indicating whether to create/initialize the Toolkit instance, with a 
default of "false". Something like this:

Toolkit:

public static synchronized Toolkit getToolkit() {
    getToolkit(false);
}

public static synchronized Toolkit getToolkit(boolean create) {
    if (TOOLKIT != null) {
        return TOOLKIT;
    }
    if (!create) throw new IllegalStateException("Toolkit not created");

    // existing code goes here....
}

The PlatformImpl startup code (and maybe a few other cases) would call 
getToolkit(true). Existing code that calls Toolkit.getToolkit would work only 
if the platform was already started, which is proably OK for many of the usages.

This presumes that the FX runtime is always started before getting to the 
various places that call getToolkit(), which might or might not be a valid 
assumption. This should not be a problem with proper JavaFX applications that 
aren't trying to be overly clever and do anything before the Application is 
launched. If there are some code paths that call getToolkit without the 
platform being properly started up, they would get an ISE. It might be a 
problem for our test framework (e.g., the StubToolkit-based tests). It would 
need to be tested.

A variation on the above: if most places can safely call the existing 
getToolkit() method, you could flip the default and call getToolkit(false) in 
the (hopefully few) places that you find are called from a static initializer.

Anyway, that's all I could come with off the top of my head.

-- Kevin


On 5/3/2018 1:18 PM, Johan Vos wrote:
Hi,

For a number of reasons, I'm looking into using SubstrateVM to bundle a
JavaFX application into a native executable. The SubstrateVM relies on an
AOT that's more aggressive than Gluon VM and it will precompile class
initializers.
I clearly see the (performance) benefits of this, but it has also
consequences that have to be taken into account.

One of those consequences is that threads that are somehow referenced via
those class initialization code should not be in a started state.

I tweaked a few initializers to avoid doing this, but the biggest impact
this has so far is on Toolkit.getToolkit().
This will set the static TOOLKIT field of Toolkit to e.g. QuantumToolkit,
and a whole bunch of objects become reachable including e.g. HashMap$Node
hence ThreadPoolExecutor$Worker and a thread is started.

As long as there is no single clinit call that uses Toolkit.getToolkit()
this is not a problem, but clearly there are class initializers that use
(indirectly) Toolkit.getToolkit() -- for example, AbstractMasterTimer.java
has a few booleans that are statically initialized to
Settings.getBoolean(), which triggers Settings.getInstance(), which uses
Toolkit.getToolkit()

While it is not impossible to modify those, it's probably some work and I
wonder if there might be an easier solution?

- Johan


Reply via email to