JDK-8326980 : [macos] JavaFX WebView severe log selecting text and pressing Caps Lock
  • Type: Bug
  • Component: javafx
  • Sub-Component: web
  • Affected Version: jfx11,8,jfx17,jfx21,jfx23
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: os_x
  • Submitted: 2024-02-28
  • Updated: 2024-12-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
jfx25Unresolved
Related Reports
Relates :  
Description
To reproduce, run the attached test.

Select any text and press Caps Lock. 

The following log shows up:

Feb 28, 2024 6:09:24 PM com.sun.javafx.webkit.InputMethodClientImpl callOnEventThread
SEVERE: InputMethodClientImpl java.util.concurrent.ExecutionException: java.lang.NullPointerException: Cannot invoke "String.substring(int, int)" because the return value of "com.sun.webkit.WebPage.getClientCommittedText()" is null
Feb 28, 2024 6:09:24 PM com.sun.javafx.webkit.InputMethodClientImpl callOnEventThread
SEVERE: InputMethodClientImpl java.util.concurrent.ExecutionException: java.lang.NullPointerException: Cannot invoke "String.substring(int, int)" because the return value of "com.sun.webkit.WebPage.getClientCommittedText()" is null

This log happens running any JavaFX version that includes the fix from JDK-8322703 (starting 22-ea+26 or 23-ea+1).
With lower JavaFX versions, the full stacktrace is:

java.lang.reflect.InvocationTargetException
        at java.desktop/sun.lwawt.macosx.LWCToolkit.checkException(LWCToolkit.java:766)
        at java.desktop/sun.lwawt.macosx.LWCToolkit.invokeAndWait(LWCToolkit.java:735)
        at java.desktop/sun.lwawt.macosx.CInputMethod.attributedSubstringFromRange(CInputMethod.java:590)
Caused by: java.lang.NullPointerException: Cannot invoke "String.substring(int, int)" because the return value of "com.sun.webkit.WebPage.getClientCommittedText()" is null
        at javafx.web@22-ea/com.sun.javafx.webkit.InputMethodClientImpl.getCommittedText(InputMethodClientImpl.java:185)
        at javafx.graphics@22-ea/javafx.scene.Scene$InputMethodRequestsDelegate.getCommittedText(Scene.java:4216)
        at javafx.swing@22-ea/javafx.embed.swing.InputMethodSupport$InputMethodRequestsAdapter.getCommittedText(InputMethodSupport.java:83)
        at java.desktop/sun.awt.im.InputMethodContext.getCommittedText(InputMethodContext.java:302)
        at java.desktop/sun.lwawt.macosx.CInputMethod$3.run(CInputMethod.java:602)
        at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:308)
        at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:771)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:722)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:716)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
        at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:746)
        at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:744)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
        at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:743)
        at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
java.lang.reflect.InvocationTargetException
        at java.desktop/sun.lwawt.macosx.LWCToolkit.checkException(LWCToolkit.java:766)
        at java.desktop/sun.lwawt.macosx.LWCToolkit.invokeAndWait(LWCToolkit.java:735)
        at java.desktop/sun.lwawt.macosx.CInputMethod.attributedSubstringFromRange(CInputMethod.java:590)
Caused by: java.lang.NullPointerException: Cannot invoke "String.substring(int, int)" because the return value of "com.sun.webkit.WebPage.getClientCommittedText()" is null
        at javafx.web@22-ea/com.sun.javafx.webkit.InputMethodClientImpl.getCommittedText(InputMethodClientImpl.java:185)
        at javafx.graphics@22-ea/javafx.scene.Scene$InputMethodRequestsDelegate.getCommittedText(Scene.java:4216)
        at javafx.swing@22-ea/javafx.embed.swing.InputMethodSupport$InputMethodRequestsAdapter.getCommittedText(InputMethodSupport.java:83)
        at java.desktop/sun.awt.im.InputMethodContext.getCommittedText(InputMethodContext.java:302)
        at java.desktop/sun.lwawt.macosx.CInputMethod$3.run(CInputMethod.java:602)
        at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:308)
        at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:771)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:722)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:716)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
        at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:746)
        at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:744)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
        at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:743)
        at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

After a quick inspection, it appears that the call to com.sun.webkit.WebPage.getClientCommittedText().substring() could use a null check to prevent the NPE.

It seems related to the issue JDK-8315495, that was closed as incomplete.

Comments
Checking Java_com_sun_webkit_WebPage_twkGetCommittedText in WebPage.cpp, https://github.com/openjdk/jfx/blob/master/modules/javafx.web/src/main/native/Source/WebKitLegacy/java/WebCoreSupport/WebPage.cpp#L2135 JNIEXPORT jstring JNICALL Java_com_sun_webkit_WebPage_twkGetCommittedText(JNIEnv *env, jobject self, jlong pPage) { ... jstring text = 0; Editor &editor = frame->editor(); if (editor.canEdit()) { ... text = t.toJavaString(env).releaseLocal(); WTF::CheckAndClearException(env); // OOME } } return text; } I see that if editor can't edit, the returned text is 0 (null), so at least there should be a NPE check at the Java side for that scenario. In any case, this issue happens only if the WebView is embedded in a JFXPanel, like in the attached test case, and the call comes from: java.desktop/sun.lwawt.macosx.CInputMethod.attributedSubstringFromRange(CInputMethod.java:590) where AttributedCharacterIterator theIterator = fIMContext.getCommittedText(location, location + length, null); Debugging the test, I can see that it takes values: location = <length of the selected text>, and length = -<location> so beginIndex = location, and endIndex = 0. I don't see any check that prevents endIndex being lower than beginIndex, so when the Caps Lock key is pressed the getCommittedText() call from Java.Desktop gets to Swing -> to Scene -> to WebPage (and to native _twkGetCommittedText) Even if the returned string from native wasn't null (just empty), another exception would arise, a StringIndexOutOfBoundsException in this case, given that endIndex is lower than beginIndex. So I see two issues here: - JavaFX/WebPage should address the possible null string coming from _twkGetCommittedText in a not editable scenario. - JavaDesktop/CInputMethod should prevent doing further calls if endIndex < beginIndex. A possible fix, for now in the JavaFX side, in com.sun.javafx.webkit.InputMethodClientImpl: public String getCommittedText(int begin, int end) { String result = callOnEventThread((Callable<String>) () -> { try { - return webPage.getClientCommittedText().substring(begin, end); + String clientCommittedText = webPage.getClientCommittedText(); + if (clientCommittedText == null) { + return null; + } + return clientCommittedText.substring(begin, end); } catch (StringIndexOutOfBoundsException e) { throw new IllegalArgumentException(e); } }); could solve this issue, preventing both the NPE and the SIOOBE exceptions.
14-03-2024

We could easily suppress the NPE, although I would want to evaluate why the selected text is returning null.
29-02-2024

As noted in the description, this bug reproduces in earlier versions of JavaFX as well, so I'm adjusting the affected versions accordingly. Prior to the fix for JDK-8322703, the error message included the full stack trace, and sometimes crashed instead of getting an NPE, but the bug was there nonetheless. Two other observations: 1. I saw this problem intermittently while testing my fix for JDK-8322703, as noted in the PR [1] (an earlier version of my fix suppressed the warnings for any exception, which was not the right approach). I had intended to file a follow-up bug, but didn't. 2. I read the description of JDK-8315495, and it seems that they were running into three different problems: the deadlock described in JDK-8221261 (now fixed), the crash described in JDK-8322703 (now fixed), and the NPE described in this bug (JDK-8326980). [1] https://github.com/openjdk/jfx/pull/1321#issuecomment-1895753776
29-02-2024