6829180: Removing focused component from a window causes a JVM crash for JDK7b50+ on WinXP/Vista
Summary: access pData on the toolkit thread
Reviewed-by: art, anthony, naoto
--- a/jdk/src/windows/native/sun/windows/awt_Component.cpp Thu Jun 04 15:18:46 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp Fri Jun 05 17:30:05 2009 +0400
@@ -1254,6 +1254,8 @@
WIN_MSG(WM_AWT_CREATECONTEXT)
WIN_MSG(WM_AWT_DESTROYCONTEXT)
WIN_MSG(WM_AWT_ASSOCIATECONTEXT)
+ WIN_MSG(WM_AWT_GET_DEFAULT_IME_HANDLER)
+ WIN_MSG(WM_AWT_HANDLE_NATIVE_IME_EVENT)
WIN_MSG(WM_AWT_PRE_KEYDOWN)
WIN_MSG(WM_AWT_PRE_KEYUP)
WIN_MSG(WM_AWT_PRE_SYSKEYDOWN)
--- a/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp Thu Jun 04 15:18:46 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp Fri Jun 05 17:30:05 2009 +0400
@@ -91,16 +91,19 @@
{
TRY;
- //get C++ Class of Focused Component
- if (peer == 0) return;
- AwtComponent* p = (AwtComponent*)JNI_GET_PDATA(peer);
- if (p == 0) return;
+ jobject selfGlobalRef = env->NewGlobalRef(self);
+ jobject peerGlobalRef = env->NewGlobalRef(peer);
+
+ EnableNativeIMEStruct *enis = new EnableNativeIMEStruct;
- p->SetInputMethod(self, useNativeCompWindow);
+ enis->self = selfGlobalRef;
+ enis->peer = peerGlobalRef;
+ enis->context = context;
+ enis->useNativeCompWindow = useNativeCompWindow;
- // use special message to call ImmAssociateContext() in main thread.
AwtToolkit::GetInstance().SendMessage(WM_AWT_ASSOCIATECONTEXT,
- reinterpret_cast<WPARAM>(p->GetHWnd()), context);
+ reinterpret_cast<WPARAM>(enis), (LPARAM)0);
+ // global refs are deleted in message handler
CATCH_BAD_ALLOC;
}
@@ -116,16 +119,18 @@
{
TRY_NO_VERIFY;
- //get C++ Class of Focused Component
- if (peer == 0) return;
- AwtComponent* p = (AwtComponent*)JNI_GET_PDATA(peer);
- if (p == 0) return;
+ jobject peerGlobalRef = env->NewGlobalRef(peer);
+ // self reference is not used
- p->SetInputMethod(NULL, TRUE);
+ EnableNativeIMEStruct *enis = new EnableNativeIMEStruct;
+ enis->self = NULL;
+ enis->peer = peerGlobalRef;
+ enis->context = NULL;
+ enis->useNativeCompWindow = JNI_TRUE;
- // use special message to call ImmAssociateContext() in main thread.
AwtToolkit::GetInstance().SendMessage(WM_AWT_ASSOCIATECONTEXT,
- reinterpret_cast<WPARAM>(p->GetHWnd()), NULL);
+ reinterpret_cast<WPARAM>(enis), (LPARAM)0);
+ // global refs are deleted in message handler
CATCH_BAD_ALLOC;
}
@@ -167,23 +172,14 @@
if (id >= java_awt_event_InputMethodEvent_INPUT_METHOD_FIRST &&
id <= java_awt_event_InputMethodEvent_INPUT_METHOD_LAST)
{
- long modifiers = p->GetJavaModifiers();
- if (msg.message==WM_CHAR || msg.message==WM_SYSCHAR) {
- WCHAR unicodeChar = L'\0';
- unicodeChar = (WCHAR)msg.wParam;
- p->SendKeyEvent(java_awt_event_KeyEvent_KEY_TYPED,
- 0, //to be fixed nowMillis(),
- java_awt_event_KeyEvent_CHAR_UNDEFINED,
- unicodeChar,
- modifiers,
- java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
- &msg);
- } else {
- MSG* pCopiedMsg = new MSG;
- *pCopiedMsg = msg;
- p->SendMessage(WM_AWT_HANDLE_EVENT, (WPARAM) FALSE,
- (LPARAM) pCopiedMsg);
- }
+ jobject peerGlobalRef = env->NewGlobalRef(peer);
+
+ // use special message to access pData on the toolkit thread
+ AwtToolkit::GetInstance().SendMessage(WM_AWT_HANDLE_NATIVE_IME_EVENT,
+ reinterpret_cast<WPARAM>(peerGlobalRef),
+ reinterpret_cast<LPARAM>(&msg));
+ // global ref is deleted in message handler
+
(env)->SetBooleanField(event, AwtAWTEvent::consumedID, JNI_TRUE);
}
@@ -373,22 +369,27 @@
Windows system creates a default input method window for the
toolkit thread.
*/
- HWND hwndIME = AwtToolkit::GetInstance().GetInputMethodWindow();
- if (hwndIME == NULL) {
- if (peer == NULL) {
- return;
- }
+
+ HWND defaultIMEHandler = AwtToolkit::GetInstance().GetInputMethodWindow();
+
+ if (defaultIMEHandler == NULL)
+ {
+ jobject peerGlobalRef = env->NewGlobalRef(peer);
- AwtComponent* p = (AwtComponent*)JNI_GET_PDATA(peer);
- if (p == NULL || (hwndIME = ImmGetDefaultIMEWnd(p->GetHWnd())) == NULL) {
- return;
+ // use special message to access pData on the toolkit thread
+ LRESULT res = AwtToolkit::GetInstance().SendMessage(WM_AWT_GET_DEFAULT_IME_HANDLER,
+ reinterpret_cast<WPARAM>(peerGlobalRef), 0);
+ // global ref is deleted in message handler
+
+ if (res == TRUE) {
+ defaultIMEHandler = AwtToolkit::GetInstance().GetInputMethodWindow();
}
-
- AwtToolkit::GetInstance().SetInputMethodWindow(hwndIME);
}
- ::SendMessage(hwndIME, WM_IME_CONTROL,
- visible ? IMC_OPENSTATUSWINDOW : IMC_CLOSESTATUSWINDOW, 0);
+ if (defaultIMEHandler != NULL) {
+ ::SendMessage(defaultIMEHandler, WM_IME_CONTROL,
+ visible ? IMC_OPENSTATUSWINDOW : IMC_CLOSESTATUSWINDOW, 0);
+ }
}
/*
@@ -417,6 +418,7 @@
// use special message to open candidate window in main thread.
AwtToolkit::GetInstance().SendMessage(WM_AWT_OPENCANDIDATEWINDOW,
(WPARAM)peerGlobalRef, MAKELONG(x, y));
+ // global ref is deleted in message handler
CATCH_BAD_ALLOC;
}
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp Thu Jun 04 15:18:46 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp Fri Jun 05 17:30:05 2009 +0400
@@ -804,8 +804,73 @@
return 0;
}
case WM_AWT_ASSOCIATECONTEXT: {
- AwtComponent *p = AwtComponent::GetComponent((HWND)wParam);
- p->ImmAssociateContext((HIMC)lParam);
+ EnableNativeIMEStruct *data = (EnableNativeIMEStruct*)wParam;
+
+ jobject peer = data->peer;
+ jobject self = data->self;
+ jint context = data->context;
+ jboolean useNativeCompWindow = data->useNativeCompWindow;
+
+ AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(peer);
+ if (comp != NULL)
+ {
+ comp->SetInputMethod(self, useNativeCompWindow);
+ comp->ImmAssociateContext((HIMC)context);
+ }
+
+ if (peer != NULL) {
+ env->DeleteGlobalRef(peer);
+ }
+ if (self != NULL) {
+ env->DeleteGlobalRef(self);
+ }
+
+ delete data;
+ return 0;
+ }
+ case WM_AWT_GET_DEFAULT_IME_HANDLER: {
+ LRESULT ret = (LRESULT)FALSE;
+ jobject peer = (jobject)wParam;
+
+ AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(peer);
+ if (comp != NULL) {
+ HWND defaultIMEHandler = ImmGetDefaultIMEWnd(comp->GetHWnd());
+ if (defaultIMEHandler != NULL) {
+ AwtToolkit::GetInstance().SetInputMethodWindow(defaultIMEHandler);
+ ret = (LRESULT)TRUE;
+ }
+ }
+
+ if (peer != NULL) {
+ env->DeleteGlobalRef(peer);
+ }
+ return ret;
+ }
+ case WM_AWT_HANDLE_NATIVE_IME_EVENT: {
+ jobject peer = (jobject)wParam;
+ AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(peer);
+ MSG* msg = (MSG*)lParam;
+
+ long modifiers = comp->GetJavaModifiers();
+ if ((comp != NULL) && (msg->message==WM_CHAR || msg->message==WM_SYSCHAR)) {
+ WCHAR unicodeChar = (WCHAR)msg->wParam;
+ comp->SendKeyEvent(java_awt_event_KeyEvent_KEY_TYPED,
+ 0, //to be fixed nowMillis(),
+ java_awt_event_KeyEvent_CHAR_UNDEFINED,
+ unicodeChar,
+ modifiers,
+ java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
+ msg);
+ } else if (comp != NULL) {
+ MSG* pCopiedMsg = new MSG;
+ *pCopiedMsg = *msg;
+ comp->SendMessage(WM_AWT_HANDLE_EVENT, (WPARAM) FALSE,
+ (LPARAM) pCopiedMsg);
+ }
+
+ if (peer != NULL) {
+ env->DeleteGlobalRef(peer);
+ }
return 0;
}
case WM_AWT_ENDCOMPOSITION: {
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.h Thu Jun 04 15:18:46 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.h Fri Jun 05 17:30:05 2009 +0400
@@ -61,6 +61,14 @@
typedef VOID (CALLBACK* IDLEPROC)(VOID);
typedef BOOL (CALLBACK* PEEKMESSAGEPROC)(MSG&);
+// Struct for _WInputMethod_enable|disableNativeIME method
+struct EnableNativeIMEStruct {
+ jobject self;
+ jobject peer;
+ jint context;
+ jboolean useNativeCompWindow;
+};
+
/*
* class JNILocalFrame
* Push/PopLocalFrame helper
--- a/jdk/src/windows/native/sun/windows/awtmsg.h Thu Jun 04 15:18:46 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awtmsg.h Fri Jun 05 17:30:05 2009 +0400
@@ -208,6 +208,8 @@
WM_AWT_CREATECONTEXT,
WM_AWT_DESTROYCONTEXT,
WM_AWT_ASSOCIATECONTEXT,
+ WM_AWT_GET_DEFAULT_IME_HANDLER,
+ WM_AWT_HANDLE_NATIVE_IME_EVENT,
WM_AWT_PRE_KEYDOWN,
WM_AWT_PRE_KEYUP,
WM_AWT_PRE_SYSKEYDOWN,