JFormDesigner / FlatLaf

FlatLaf - Swing Look and Feel (with Darcula/IntelliJ themes support)
https://www.formdev.com/flatlaf/
Apache License 2.0
3.31k stars 265 forks source link

AWT native code freezee at sun.awt.windows.WGlobalCursorManager#findHeavyweightUnderCursor #878

Open VISTALL opened 1 month ago

VISTALL commented 1 month ago

Hello. I'm testing FlatLaf as default laf for Consulo IDE (https://github.com/consulo), which is an IDEA fork.

I want replace internal laf implementation by FlatLaf, but catch very strange freeze at sun.awt.windows.WGlobalCursorManager#findHeavyweightUnderCursor. Freeze can appear in random time (there no specific time when, app can start - I can do something, and catch UI lock, or just at start)

JRE: 21.0.2+13-b375.1 (JetBrains s.r.o.) JVM: 21.0.2+13-b375.1 (OpenJDK 64-Bit Server VM)

Using last library version

Also tested with Adoptium JDK 21 - some issue.

Any guess?

"AWT-EventQueue-0@4684" tid=0x56 nid=NA runnable
  java.lang.Thread.State: RUNNABLE
     blocks AWT-Windows@3479
      at sun.awt.windows.WGlobalCursorManager.findHeavyweightUnderCursor(WGlobalCursorManager.java:-1)
      at sun.awt.GlobalCursorManager._updateCursor(GlobalCursorManager.java:178)
      at sun.awt.GlobalCursorManager.updateCursorImmediately(GlobalCursorManager.java:95)
      at sun.awt.windows.WComponentPeer.updateCursorImmediately(WComponentPeer.java:710)
      at java.awt.Component.updateCursorImmediately(Component.java:3259)
      at java.awt.Container.validate(Container.java:1672)
      at com.formdev.flatlaf.ui.FlatRootPaneUI$FlatRootLayout.layoutContainer(FlatRootPaneUI.java:630)
      at java.awt.Container.layout(Container.java:1541)
      at java.awt.Container.doLayout(Container.java:1530)
      at java.awt.Container.validateTree(Container.java:1725)
      at java.awt.Container.validate(Container.java:1660)
      - locked <0x5d93> (a java.awt.Component$AWTTreeLock)
      at javax.swing.RepaintManager$3.run(RepaintManager.java:760)
      at javax.swing.RepaintManager$3.run(RepaintManager.java:758)
      at java.security.AccessController.executePrivileged(AccessController.java:778)
      at java.security.AccessController.doPrivileged(AccessController.java:400)
      at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
      at javax.swing.RepaintManager.validateInvalidComponents(RepaintManager.java:757)
      at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1911)
      at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
      at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:781)
      at java.awt.EventQueue$4.run(EventQueue.java:728)
      at java.awt.EventQueue$4.run(EventQueue.java:722)
      at java.security.AccessController.executePrivileged(AccessController.java:778)
      at java.security.AccessController.doPrivileged(AccessController.java:400)
      at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
      at java.awt.EventQueue.dispatchEvent(EventQueue.java:750)
      at consulo.desktop.awt.ui.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:769)
      at consulo.desktop.awt.ui.IdeEventQueue._dispatchEvent(IdeEventQueue.java:680)
      at consulo.desktop.awt.ui.IdeEventQueue.lambda$dispatchEvent$5(IdeEventQueue.java:367)
      at consulo.desktop.awt.ui.IdeEventQueue$$Lambda/0x0000000800bfe2d0.compute(Unknown Source:-1)
      at consulo.application.impl.internal.progress.CoreProgressManager.computePrioritized(CoreProgressManager.java:770)
      at consulo.desktop.awt.ui.IdeEventQueue.lambda$dispatchEvent$6(IdeEventQueue.java:366)
      at consulo.desktop.awt.ui.IdeEventQueue$$Lambda/0x0000000800bfe090.run(Unknown Source:-1)
      at consulo.desktop.awt.ui.IdeEventQueue.dispatchEvent(IdeEventQueue.java:405)
      at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207)
      at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
      at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
      at java.awt.EventDispatchThread.run(EventDispatchThread.java:92)
VISTALL commented 1 month ago

Disabling window decoration (-Dflatlaf.useWindowDecorations=false) looks like fix issue

VISTALL commented 1 month ago

My research. I attached VS for application and found this:

Native Call Stack image

Deeper

image

Found source code

image

And I'm stuck at that point

DevCharly commented 2 weeks ago

Not sure how I could help 😕 Don't see any relation to FlatLaf in provided information.

The stack in your initial post shows that thread AWT-EventQueue-0 "blocks AWT-Windows@3479". Could you post the stack of the blocked thread AWT-Windows?

VISTALL commented 2 weeks ago

Hello. I'm 100% sure stuck in native code inside FlatLaf library code, but I'm don't known how found the problem

VISTALL commented 2 weeks ago

I will try

VISTALL commented 2 weeks ago

Sometimes lock not inside AppMenu - but same position (heavy cursor find). Here another thread image

DevCharly commented 2 weeks ago

I think it would be better to use jstack to get more information (stack of all threads, blocked threads, etc).

See https://intellij-support.jetbrains.com/hc/en-us/articles/206544899-Getting-a-thread-dump-when-IDE-hangs-and-doesn-t-respond

VISTALL commented 2 weeks ago

log.txt

DevCharly commented 2 weeks ago

This is interesting.

Thread AWT-Windows is blocked while handling WM_NCHITTEST message:

"AWT-Windows" #71 [12588] daemon prio=6 os_prio=0 cpu=421.88ms elapsed=132.46s tid=0x0000020ac2435ed0 nid=12588 waiting for monitor entry  [0x000000b0657fd000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at java.awt.Component.getLocationOnScreen(java.desktop@21.0.3/Component.java:2118)
==> - waiting to lock <0x000000020713be18> (a java.awt.Component$AWTTreeLock)
    at javax.swing.SwingUtilities.convertPointToScreen(java.desktop@21.0.3/SwingUtilities.java:437)
    at javax.swing.SwingUtilities.convertPoint(java.desktop@21.0.3/SwingUtilities.java:197)
==> at consulo.ide.impl.idea.ui.BalloonImpl$MyComponent.contains(consulo.ide.impl@3-SNAPSHOT/BalloonImpl.java:1953)
    at com.formdev.flatlaf.ui.FlatTitlePane.isTitleBarCaptionAt(com.formdev.flatlaf/FlatTitlePane.java:1082)
    at com.formdev.flatlaf.ui.FlatTitlePane.isTitleBarCaptionAt(com.formdev.flatlaf/FlatTitlePane.java:1127)
    at com.formdev.flatlaf.ui.FlatTitlePane.captionHitTest(com.formdev.flatlaf/FlatTitlePane.java:1077)
    at com.formdev.flatlaf.ui.FlatTitlePane$$Lambda/0x0000020a7c6c0240.test(com.formdev.flatlaf/Unknown Source)
==> at com.formdev.flatlaf.ui.FlatWindowsNativeWindowBorder$WndProc.onNcHitTest(com.formdev.flatlaf/FlatWindowsNativeWindowBorder.java:379)
    at sun.awt.windows.WToolkit.eventLoop(java.desktop@21.0.3/Native Method)
    at sun.awt.windows.WToolkit.run(java.desktop@21.0.3/WToolkit.java:360)
    at java.lang.Thread.runWith(java.base@21.0.3/Thread.java:1596)
    at java.lang.Thread.run(java.base@21.0.3/Thread.java:1583)

Here is thread AWT-EventQueue-0, which owns the AWT lock:

"AWT-EventQueue-0" #86 [19664] prio=6 os_prio=0 cpu=5921.88ms elapsed=131.73s tid=0x0000020ac2434490 nid=19664 runnable  [0x000000b0633fe000]
   java.lang.Thread.State: RUNNABLE
    at sun.awt.windows.WGlobalCursorManager.findHeavyweightUnderCursor(java.desktop@21.0.3/Native Method)
    at sun.awt.GlobalCursorManager._updateCursor(java.desktop@21.0.3/GlobalCursorManager.java:178)
    at sun.awt.GlobalCursorManager.updateCursorImmediately(java.desktop@21.0.3/GlobalCursorManager.java:95)
    at sun.awt.windows.WComponentPeer.updateCursorImmediately(java.desktop@21.0.3/WComponentPeer.java:710)
    at java.awt.Component.updateCursorImmediately(java.desktop@21.0.3/Component.java:3259)
    at java.awt.Container.validate(java.desktop@21.0.3/Container.java:1672)
    at com.formdev.flatlaf.ui.FlatRootPaneUI$FlatRootLayout.layoutContainer(com.formdev.flatlaf/FlatRootPaneUI.java:630)
    at java.awt.Container.layout(java.desktop@21.0.3/Container.java:1541)
    at java.awt.Container.doLayout(java.desktop@21.0.3/Container.java:1530)
    at java.awt.Container.validateTree(java.desktop@21.0.3/Container.java:1725)
    at java.awt.Container.validate(java.desktop@21.0.3/Container.java:1660)
==> - locked <0x000000020713be18> (a java.awt.Component$AWTTreeLock)
    at javax.swing.RepaintManager$3.run(java.desktop@21.0.3/RepaintManager.java:762)
    at javax.swing.RepaintManager$3.run(java.desktop@21.0.3/RepaintManager.java:760)

So the problem is causes by consulo.ide.impl.idea.ui.BalloonImpl$MyComponent.contains(x, y), which invokes SwingUtilities.convertPoint() on thread AWT-Windows while AWT is locked on thread AWT-EventQueue-0.

If you (temporary) change consulo.ide.impl.idea.ui.BalloonImpl$MyComponent.contains(x, y) to simply return false, the application should no longer freeze.

On FlatLaf side, I'll remove the invocation of Component.contains(x, y) to avoid that problem/risk. I'll also review the code that runs on thread AWT-Windows...

DevCharly commented 2 weeks ago

fixed in latest 3.6-SNAPSHOT: https://github.com/JFormDesigner/FlatLaf#snapshots

VISTALL commented 2 weeks ago

Good day. I will test, thanks for possible fix :)

VISTALL commented 2 weeks ago

Looks like - bug fixed, I can't reproduce for now. I had misscheck AWT-Windows thread locking.

This logic also exists in IDEA (https://github.com/JetBrains/intellij-community/blob/master/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java#L2011)

BalloonImpl its notifications,etc component ui.