apache / netbeans

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

Lazy init SMO backend and increase timeout #7587

Closed mbien closed 1 month ago

mbien commented 1 month ago

So I noticed since https://github.com/apache/netbeans/pull/7569 this exception when NB is started and closed before the maven indexer is initialized:

INFO [org.netbeans.NetigsoModule]: Can't load com.google.gson.JsonElement in package com.google.gson
java.lang.IllegalStateException: Bundle "reference:file:ide/modules/com-google-gson.jar" has been uninstalled
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.checkValid(AbstractBundle.java:1175)
    at org.eclipse.osgi.framework.internal.core.BundleHost.checkLoader(BundleHost.java:183)
    at org.eclipse.osgi.framework.internal.core.BundleHost.loadClass(BundleHost.java:225)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadClass(AbstractBundle.java:1212)
    at org.netbeans.core.netigso.NetigsoLoader.doLoadClass(NetigsoLoader.java:89)
[catch] at org.netbeans.NetigsoModule$DelegateCL.doLoadClass(NetigsoModule.java:236)
    at org.netbeans.ProxyClassLoader.selfLoadClass(ProxyClassLoader.java:260)
    at org.netbeans.ProxyClassLoader.doFindClass(ProxyClassLoader.java:189)
    at org.netbeans.ProxyClassLoader.loadClass(ProxyClassLoader.java:140)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:528)
    at org.apache.maven.search.backend.smo.SmoSearchBackendFactory.create(SmoSearchBackendFactory.java:48)
    at org.apache.maven.search.backend.smo.SmoSearchBackendFactory.createDefault(SmoSearchBackendFactory.java:41)
    at org.netbeans.modules.maven.indexer.NexusRepositoryIndexerImpl.<init>(NexusRepositoryIndexerImpl.java:185)
    at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:501)
    at java.base/java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:132)
    at java.base/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:259)
    at java.base/java.lang.Class.newInstance(Class.java:804)
    at org.openide.util.lookup.implspi.SharedClassObjectBridge.newInstance(SharedClassObjectBridge.java:41)
    at org.openide.util.lookup.MetaInfServicesLookup$Item.getInstance(MetaInfServicesLookup.java:490)
    at org.openide.util.lookup.AbstractLookup$R.allInstances(AbstractLookup.java:1033)
    at org.openide.util.lookup.AbstractLookup$R.allInstances(AbstractLookup.java:1013)
    at org.openide.util.lookup.ProxyLookup$LazyCollection.computeSingleResult(ProxyLookup.java:1348)
    at org.openide.util.lookup.ProxyLookup$LazyCollection.computeDelegate(ProxyLookup.java:1186)
    at org.openide.util.lookup.ProxyLookup$LazyCollection.access$900(ProxyLookup.java:1114)
    at org.openide.util.lookup.ProxyLookup$LazyCollection$1.hasNext(ProxyLookup.java:1314)
    at org.netbeans.modules.maven.indexer.OnStop.run(OnStop.java:48)
    at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:1403)
    at org.netbeans.modules.openide.util.GlobalLookup.execute(GlobalLookup.java:45)
    at org.openide.util.lookup.Lookups.executeWith(Lookups.java:287)
    at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:2018)

I am not completely sure why this happens. The gson wrapper can be found just fine when NexusRepositoryIndexerImpl is initialized normally, but when it is loaded from for the first time https://github.com/apache/netbeans/blob/1b31400eaaa7d118ebb7c2b053f0b96c95f987e3/java/maven.indexer/src/org/netbeans/modules/maven/indexer/OnStop.java#L48-L52 it causes the exception. Lazy loading SMO fixes it.

mbien commented 1 month ago

I am no osgi expert but this would be a plausible explanation:

so this is mostly harmless, lazy loading SMO is an easy fix and should have no side effects

mbien commented 1 month ago

thanks for the review, I will try to split cleanup the rest from now on again.

My opinion about misuse of records for final classes with immutable fields:

if its a private or package private non-API utility, I would personally go with whatever is most concise or reads best. There absolutely are problems with record overuse, but this is often a problem in API. Interfaces on top and records on the bottom can look convenient, but as soon you need an additional field which can't be passed through the canonical constructor you designed yourself into a corner and have to recompute state in methods again and again.

So I do agree that record overuse can cause problems, but I think in situations where you can change back to a final class at any point in future - it is no real problem. You get a good toString() for free which helps when debugging.

var overuse however... does actually obfuscate code since it hides types entirely, now add inline hints again and it often uses more space than without var - but you know that this is my personal pet peeve ;)