<AWT Dev> [16] RFR 8249183: JVM crash in "AwtFrame::WmSize" method

Anton Litvinov anton.litvinov at oracle.com
Mon Aug 24 23:26:04 UTC 2020

Hi Sergey,

Thank you for confirmation about which code in the function 
"AwtFrame::WmSize" you suggested to move to Java code level. I agree 
with your suggestion and also came to a conclusion in my previous e-mail 
that only this code can be moved out. The new version of the fix, which 
implements your suggestion, was created and tested. Could you please 
look at the second fix version.

Webrev (the 2nd version): 

I studied the involved C++ code flow and confirm that the next 3 C++ 
function calls from the defined by you part of the function 
"AwtFrame::WmSize" do not alter any fields of the involved C++ object 
"AwtFrame", "AwtDialog" and are just nothing else then the next 3 
corresponding Java expressions:

1.  C++ function call 
"SendWindowEvent(java_awt_event_WindowEvent_WINDOW_ICONIFIED);" --> Java 
expression "sun.awt.windows.WComponentPeer.postEvent(new 
TimedWindowEvent((Window) target, WindowEvent.WINDOW_ICONIFIED, null, 0, 
0, System.currentTimeMillis()));"

2.  C++ function call 
"SendWindowEvent(java_awt_event_WindowEvent_WINDOW_DEICONIFIED);" --> 
Java expression "sun.awt.windows.WComponentPeer.postEvent(new 
TimedWindowEvent((Window) target, WindowEvent.WINDOW_DEICONIFIED, null, 
0, 0, System.currentTimeMillis()));"

3.  C++ function call "SendWindowStateEvent(oldState, newState);" --> 
Java expression "sun.awt.windows.WComponentPeer.postEvent(new 
TimedWindowEvent((Window) target, WindowEvent.WINDOW_STATE_CHANGED, 
null, oldState, newState, System.currentTimeMillis()));"

Regarding your remark about the need to take into account 
"getExtendedState" Java method, I agree with you and confirm that it is 
impossible that this method will be called on not instance of 
"WFramePeer" Java class and agree that there is no need to change code 
related to "getExtendedState" method.


Change 1 - The pointed by you part of "AwtFrame::WmSize" function was 
reimplemented in Java language as the new method 
"sun.awt.windows.WWindowPeer.notifyWindowStateChanged(int oldState, int 
newState)" in the file "WWindowPeer.java". JNI Invocation of this new 
Java method was wrapped in the new C++ function "void 
AwtWindow::NotifyWindowStateChanged(jint oldState, jint newState)" in 
the file "awt_Window.cpp".

Change 2 - The function "void SendWindowStateEvent(int oldState, int 
newState);" was removed from the C++ class "AwtFrame" in the files 
"awt_Frame.h", "awt_Frame.cpp", because it is not called from anywhere 
in JDK source code after this fix.

Change 3 - Java method ID variable "static jmethodID 
setExtendedStateMID;" with code using it was removed from the C++ class 
"AwtFrame" in the files "awt_Frame.h", "awt_Frame.cpp", because it is 
not called from anywhere in JDK source code after this fix.

Thank you,

On 20/08/2020 05:21, Sergey Bylokhov wrote:
> On 19.08.2020 09:16, Anton Litvinov wrote:
>> Thank you very much for review of this fix. I have been evaluating 
>> your suggestion and my opinion is following. On macOS that code was 
>> implemented already from the moment JDK 7 code for macOS appeared. 
>> Although macOS-specific platform-dependent code on Java level has 
>> some similarities with Windows platform-dependent code on Java level, 
>> native platform-dependent code is very different between these two OSes.
>> Of course it is technically possible to move some part of 
>> "AwtFrame::WmSize" function 
>> (http://hg.openjdk.java.net/jdk/client/file/2c7b5ae39c19/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp#l915) 
>> to some new method or methods in "sun.awt.windows.WWindowPeer", but 
>> that fix will be much bigger, will require different changes both in 
>> C++ and Java code, and will be necessary to prove that such 
>> refactoring did not break anything previously working well. 
>> "AwtFrame::WmSize" function depends on:
>> - "AwtFrame" class fields: "m_iconic", "m_zoomed" through the 
>> functions: "isIconic()", "isZoomed()", "setIconic(BOOL)", 
>> "setZoomed(BOOL)".
>> - Win32 API constants: "SIZE_MINIMIZED", "SIZE_MAXIMIZED".
>> - Call to the function "AwtWindow::UpdateSecurityWarningVisibility" 
>> is not movable to Java level.
> No I did not meant to move the whole "AwtFrame::WmSize" to the java, 
> but only the part related for notification, same as on mac.
> So instead of calling " AwtFrame::setExtendedStateMID," from the 
> native, just call something like "WWindowPeer.notifyState(int old, int 
> new, zoom, iconify,... etc)", and on
> the java side call all necessary things like on mac:
> http://hg.openjdk.java.net/jdk/jdk/file/6b984aa424e3/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java#l661 
>  - postEvent iconify/zoom;
>  - postWindowStateChangedEvent(newWindowState);
> etc
> Probably this part of the code in awt_Frame.cpp can be moved to 
> "WWindowPeer.notifyState(...)?
>         DTRACE_PRINTLN2("AwtFrame::WmSize: reporting state change %x 
> -> %x",
>                 oldState, newState);
>         // sync target with peer
>         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
>         env->CallVoidMethod(GetPeer(env), 
> AwtFrame::setExtendedStateMID, newState);
>         // report (de)iconification to old clients
>         if (changed & java_awt_Frame_ICONIFIED) {
>             if (newState & java_awt_Frame_ICONIFIED) {
> SendWindowEvent(java_awt_event_WindowEvent_WINDOW_ICONIFIED);
>             } else {
> SendWindowEvent(java_awt_event_WindowEvent_WINDOW_DEICONIFIED);
>             }
>         }
>         // New (since 1.4) state change event
>         SendWindowStateEvent(oldState, newState);
>> It looks that only contents of "if (changed != 0) {" block 
>> (http://hg.openjdk.java.net/jdk/client/file/2c7b5ae39c19/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp#l975) 
>> can be moved to some new Java method. But what to do with JNI 
>> invocation of "getExtendedState()" method 
>> (http://hg.openjdk.java.net/jdk/client/file/2c7b5ae39c19/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp#l281).
>> To my mind, such refactoring will not give much benefit, new Java 
>> method or methods will not be used from anywhere else, but it will be 
>> required to change code which currently works stably and maybe the 
>> changes will bring some new problems. I would prefer to make the fix 
>> as narrow as possible for this not very usual scenario leading to the 
>> crash.
>> By doing this minimal version of the fix, I tried to avoid even JNI 
>> usage without the need. If you do not like this custom flag, then 
>> would you agree for its change to a normal check of peer object class 
>> using "instanceof" operator?
>> For example, to use instead of this flag the next if condition in 
>> "awt_Frame.cpp":
>> "jobject peer = GetPeer();
>> if ((peer != NULL) && (JNU_IsInstanceOfByName(env, peer, 
>> "sun/awt/windows/WFramePeer") > 0)) {"
>> Or if you do not like variant with "instanceof" operator, then 
>> instead of introduction any checks anywhere, I can suggest you as 
>> another alternative option to implement 2 new empty private methods: 
>> "int getExtendedState()", "void setExtendedState(int)" in the class 
>> "sun.awt.windows.WWindowPeer".
> Do we really need to change the code related to the "getExtendedState" 
> during creation of AWTFrame?
> That one should never be used by the AwtDialog, so the crash is kind 
> of assertion that something go wrong already.

More information about the awt-dev mailing list