clinit and threads
Kevin Rushforth
kevin.rushforth at oracle.com
Thu May 3 22:03:04 UTC 2018
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
More information about the openjfx-dev
mailing list