apache / netbeans

Apache NetBeans
https://netbeans.apache.org/
Apache License 2.0
2.69k stars 853 forks source link

ActiveReferenceQueue floors processor #5878

Open SirIntellegence opened 1 year ago

SirIntellegence commented 1 year ago

Apache NetBeans version

Apache NetBeans 18 release candidate

What happened

When building my platform App project, Netbeans floors my processor for no reason at all after a build or two. From what I can tell, a new ActiveQueue is started when the MIMEResolverProcessor processes the Mime attribute in the source file. This can apparently also happen by the background text analyzer since it does a build too. I think this is due to the class loaders being different or something? Not sure. I have checked the code and found that ActiveQueue.activeReferenceQueue is null in one thread, but NOT in the other one. This appears to not be a primary issue as they just wait for things to remove. The issue happens when they do go to do that. Ah, yes... You see... Once they do that, they get stick an a while (true) loop of sorts. When the system detects that this "instance" isn't the original one (I have no idea how that happens BTW since their loaders are different). Somehow, they realize that they aren't the running ActiveQueue.Daemon thread and they throw InterruptedExceptions to try to exit their loop... which is then caught right under the thread's while (true) statement and ignored. So they just loop, throwing and catching an exception repeatedly.

How to reproduce

CpuFloorIssue.zip Project attached. Perform a build of it. Do a clean build to trigger it again. My project does it every-time I build, but it is an actual application and therefore bigger.

Did this work correctly in an earlier version?

No / Don't know

Operating System

Mac Mini 2018 with OS 13.2.1

JDK

OpenJDK 64-Bit Server VM Temurin-19.0.1+10 (build 19.0.1+10, mixed mode, sharing)

Apache NetBeans packaging

Own source build

Anything else

A short-term workaround would be to not swallow the exception if the current thread isn't the right one, but I don't think that would just fix the issue.

Are you willing to submit a pull request?

No

neilcsmith-net commented 1 year ago

I tested with the provided project. I cannot replicate the CPU usage / interrupt side of this. But for every build a new ActiveQueue.Daemon thread is created. These are loaded by a child classloader of AntBridge$AddJavacClassLoader. There also seems to be an extra one created by the CachingArchiveClassLoader in parsing.

I have an Ant platform project that uses MIMEResolverProcessor but via @MimeResolver.ExtensionRegistration and no extra queues are created there. More testing needed!

SirIntellegence commented 1 year ago

Well, that is interesting. This may actually be related to something else. Not sure that is something that could be fixed easily or at all... I am building from a revision based from https://github.com/apache/netbeans/tree/release121. Apparently that version of ActiveQueue doesn't play nice with Java19... removeSuper calls remove(0), which calls remove() in Java 19, which throws an InterruptedException. Being able to "unload"/terminate the tread like a process would be nice, but I highly doubt Java allows that.

mbien commented 1 year ago

I am building from a revision based from https://github.com/apache/netbeans/tree/release121 Apparently that version of ActiveQueue doesn't play nice with Java19... removeSuper calls remove(0), which calls remove()...

this was fixed in NB 14 via #4130

where do you see this performance issue? in NB 18rc or in 12.1?

neilcsmith-net commented 1 year ago

where do you see this performance issue? in NB 18rc or in 12.1?

As far as I can tell, there are two bugs in play here. I believe the application being built is based on 12.1, so why the infinite loop happens, and was fixed in 4130. But even building the example against the current platform leads to multiple queues being created that are never cleared up.

Setting javac.fork=true in the project properties of the individual module seems to stop most of the additional queues being created in the JVM of the IDE, except for the parsing one. I think this is caused by use of a weak file listener in the annotation processor, along with some classloading tricks going on.