arunkumar-h opened a new issue, #9035:
URL: https://github.com/apache/netbeans/issues/9035
### Apache NetBeans version
Apache NetBeans 28
### What happened
The "Active Reference Queue Daemon" thread in NetBeans Platform RELEASE130
(version 13.0 / 9.6) consumes nearly 100% of a CPU core continuously, even when
the application is idle. This is caused by excessive calls to the native
`Throwable.fillInStackTrace()` method in the exception handling code within
`org.openide.util.lookup.implspi.ActiveQueue$Impl`.
## Environment
- **NetBeans Platform Version:** RELEASE130 (NetBeans 13.0, version 9.6,
February 2022)
- **Affected JAR:** `org-openide-util-lookup-RELEASE130.jar` (184 KB)
- **Java Version:** Reproduced on both Java 17.0.13 and Java 21.0.8
- **Operating System:** Linux (also reproducible on other platforms)
- **Product Type:** NetBeans Platform-based application (Swing application
running via Webswing)
### Language / Project Type / NetBeans Component
_No response_
### How to reproduce
1. Create a NetBeans Platform application using RELEASE130
2. Launch the application
3. Monitor CPU usage using `top` or similar tool
4. Observe that a Java process consumes ~100% of one CPU core
5. Take a thread dump: `jstack <pid> > threaddump.txt`
6. Examine the "Active Reference Queue Daemon" thread
### Did this work correctly in an earlier version?
No / Don't know
### Operating System
Red Hat Enterprise Linux release 8.10 (Ootpa)
### JDK
21
### Apache NetBeans packaging
Other, Apache NetBeans platform
### Anything else
## Actual Behavior
The "Active Reference Queue Daemon" thread runs continuously in a `RUNNABLE`
state, consuming nearly 100% of a CPU core. Thread dump shows:
```
"Active Reference Queue Daemon" #53 daemon prio=1 os_prio=0 cpu=467761.57ms
elapsed=517.51s tid=0x00007f24346b3420 nid=487222 runnable
java.lang.Thread.State: RUNNABLE
at java.lang.Throwable.fillInStackTrace([email protected]/Native Method)
at
java.lang.Throwable.fillInStackTrace([email protected]/Throwable.java:820)
- locked <0x000000071a8c52c8> (a java.lang.InterruptedException)
at java.lang.Throwable.<init>([email protected]/Throwable.java:258)
at java.lang.Exception.<init>([email protected]/Exception.java:55)
at
java.lang.InterruptedException.<init>([email protected]/InterruptedException.java:57)
at
org.openide.util.lookup.implspi.ActiveQueue$Impl.remove(ActiveQueue.java:66)
at
java.lang.ref.ReferenceQueue.remove([email protected]/ReferenceQueue.java:214)
at
org.openide.util.lookup.implspi.ActiveQueue$Impl.removeSuper(ActiveQueue.java:70)
at
org.openide.util.lookup.implspi.ActiveQueue$Daemon.run(ActiveQueue.java:115)
```
**Key observations:**
- The thread is in `RUNNABLE` state (not `WAITING`)
- Accumulated CPU time: 467,761ms over 517 seconds = ~90% CPU usage
- Continuous calls to `fillInStackTrace()` native method
- New `InterruptedException` objects are being created repeatedly
## Expected Behavior
The "Active Reference Queue Daemon" thread should spend most of its time in
a `WAITING` state, blocking on `ReferenceQueue.remove()`. CPU usage should be
minimal (< 5%) when the application is idle.
**Expected thread dump (from RELEASE111):**
```
"Active Reference Queue Daemon" daemon prio=1 cpu=2.86ms elapsed=517.51s
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:155)
- locked <0x00000006c0a21a98> (a java.lang.ref.ReferenceQueue$Lock)
at
org.openide.util.lookup.implspi.ActiveQueue$Impl.removeSuper(ActiveQueue.java:70)
at
org.openide.util.lookup.implspi.ActiveQueue$Daemon.run(ActiveQueue.java:115)
```
## Root Cause Analysis
### The Bug
In RELEASE130, the `ActiveQueue$Impl` class creates **new**
`InterruptedException` objects in its catch blocks instead of re-throwing
existing exceptions:
**Problematic code pattern in RELEASE130:**
```java
catch (InterruptedException e) {
throw new InterruptedException(); // BUG: Creates new exception
}
```
### Why This Causes High CPU
1. The daemon calls `ReferenceQueue.remove(timeout)` in a loop
2. When the timeout expires, Java throws `InterruptedException` (normal
behavior)
3. The catch block creates a **new** `InterruptedException`
4. The exception constructor calls `fillInStackTrace()` - a **native
method** that:
- Walks the entire call stack
- Creates `StackTraceElement[]` array
- Captures all frames, line numbers, etc.
- Takes significant CPU time
5. The loop repeats immediately
6. **Result:** Continuous CPU burn from stack trace generation
### Comparison with RELEASE111
**RELEASE111 (Working) - CPU usage 2.86ms:**
```java
catch (InterruptedException e) {
throw e; // Re-throws existing exception - no overhead
}
```
**RELEASE130 (Broken) - CPU usage 467,761ms:**
```java
catch (InterruptedException e) {
throw new InterruptedException(); // Creates new exception - expensive!
}
```
[webswing_ticket_threaddump_20251124_010426.txt](https://github.com/user-attachments/files/23711354/webswing_ticket_threaddump_20251124_010426.txt)
### Are you willing to submit a pull request?
No
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists