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

Reply via email to