Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazy init SMO backend and increase timeout #7587

Merged
merged 1 commit into from
Jul 17, 2024
Merged

Conversation

mbien
Copy link
Member

@mbien mbien commented Jul 16, 2024

  • initialize SMO backend only when needed
  • bump request timeout to 15s, since the response time is fairly unpredictable
  • small java 17 renovation: instanceof, records, Stream/Colleciton API

So I noticed since #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

for (RepositoryIndexerImplementation rii : Lookup.getDefault().lookupAll(RepositoryIndexerImplementation.class)) {
if (rii instanceof NexusRepositoryIndexerImpl) {
((NexusRepositoryIndexerImpl)rii).shutdownAll();
}
}

it causes the exception. Lazy loading SMO fixes it.

 - initialize SMO backend only when needed
 - bump request timeout to 15s, since the response time is fairly
   unpredictable
 - java 17 renovation: instanceof, records, Stream/Colleciton API
@mbien mbien added Maven [ci] enable "build tools" tests ci:dev-build [ci] produce a dev-build zip artifact (7 days expiration, see link on workflow summary page) labels Jul 16, 2024
@mbien mbien added this to the NB23 milestone Jul 16, 2024
@mbien
Copy link
Member Author

mbien commented Jul 17, 2024

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

  • when NB shuts down it shuts down the osgi impl, this prevents new osgi jars from loading
  • now NB runs the on-stop task which calls Lookup.getDefault().lookupAll(RepositoryIndexerImplementation.class))
  • this can initialize NexusRepositoryIndexerImpl if it wasn't used yet, osgi classloading is essentially disabled and will now throw Bundle "reference:file:ide/modules/com-google-gson.jar" has been uninstalled

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

Copy link
Contributor

@matthiasblaesing matthiasblaesing left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks sane to me.

The following is my personal opinion and not meant to keep this from being merged:
I'm not a big fan of changing files "just because" though. I think the core change is in NexusRepositoryIndexer everything else is unrelated. And in there I think the change to WagonFetcher is a misuse of record. To me the intention of record is to act as an immutable data carrier, which is not the case here. Of course it can be used as it is, to me this looks like something I would not use.

@mbien
Copy link
Member Author

mbien commented Jul 17, 2024

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 ;)

@mbien mbien merged commit 31a270c into apache:master Jul 17, 2024
33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ci:dev-build [ci] produce a dev-build zip artifact (7 days expiration, see link on workflow summary page) Maven [ci] enable "build tools" tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants