To be able to properly support static builds on Windows in
[JDK-8346377](https://bugs.openjdk.org/browse/JDK-8346377), we cannot use
`DllMain`, for two reasons:
1) This is not called for statically linked libraries, and
2) There are multiple `DllMain` definitions throughout the JDK native
libraries, causing name collisions.
While it could have been possible to keep the `DllMain` function for non-static
builds and just use an alternative solution for static builds, I think it is
preferable to have a single solution that works as well for both static and
dynamic builds.
In this case, the `DllMain` function did two things:
1) At startup, it called SetModuleHandle. This has been moved to the
`JNI_OnLoad` function, which is called by the JVM right after loading the DLL,
or in the case of a static build, when the `awt` native library has been
requested.
2) At DLL unload -- for debug builds only -- it "disabled" the mutexes for the
DTrace and DMem debug systems. In this case, "disable" means writing NULL to
the mutexes, causing any further calls to the continue without locking, since
the enter/exit calls only do the locking if the mutex is not NULL. (This is
pre-existing code so I am not discussing the soundness of this approach.)
But why did we need to do that? After the DLL unloading, which is done by
Windows when the process is exiting, no code should be executing in AWT, right?
No, wrong. There are three static objects, one instance of AwtDebugSupport and
two instances of GDIHashtable, and the destructors of these objects are called
by Windows at the time of process shutdown. I have not been able to confirm
that the `DllMain` code is guaranteed to be called before the destructors are
called, so I guess the fact that this ever worked has just been a lucky
coincidence.
I have solved this by disabling the mutexes in the destructors themselves,
thereby guaranteeing that they are disabled before the last few calls to the
DTrace/DMem calls are made. There is no guarantee in which order these
destructors are made, so I do the same on both locations. (There is no bad
effect from calling these twice in a row, it's just setting a mutex to NULL).
Finally, I have wrapped the `DEF_JNI_OnLoad` function in `extern "C" { ... }`.
This is needed since DEF_JNI_OnLoad is a macro that actually creates two
functions, where one is a wrapper calling the other which has a generated name,
and without this, the C++ name mangling messed things up. (To be clear: this
means that the JNI_OnLoad function has never been called on Windows, but since
it did not do anything of substance before, nobody noticed this.)
-------------
Commit messages:
- Merge branch 'master' into dll-main-in-libawt
- 8346388: Cannot use DllMain in libawt for static builds
Changes: https://git.openjdk.org/jdk/pull/22790/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=22790&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8346388
Stats: 61 lines in 3 files changed: 35 ins; 26 del; 0 mod
Patch: https://git.openjdk.org/jdk/pull/22790.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/22790/head:pull/22790
PR: https://git.openjdk.org/jdk/pull/22790