Iterate over contained versions only.
diff --git a/platform/o.n.bootstrap/src/org/netbeans/JarClassLoader.java b/platform/o.n.bootstrap/src/org/netbeans/JarClassLoader.java
index 8a56279..0663295 100644
--- a/platform/o.n.bootstrap/src/org/netbeans/JarClassLoader.java
+++ b/platform/o.n.bootstrap/src/org/netbeans/JarClassLoader.java
@@ -30,6 +30,7 @@
import java.lang.instrument.IllegalClassFormatException;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
@@ -53,6 +54,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeSet;
import java.util.Vector;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
@@ -77,6 +79,12 @@
* @author Petr Nejedly
*/
public class JarClassLoader extends ProxyClassLoader {
+ //
+ // When making changes to this file, check if
+ // platform/netbinox/src/org/netbeans/modules/netbinox/JarBundleFile.java
+ // should also be adjusted. At least the multi-release handling is similar.
+ //
+
private static Stamps cache;
private static final Name MULTI_RELEASE = new Name("Multi-Release");
private static final int BASE_VERSION = 8;
@@ -87,7 +95,7 @@
try {
Object runtimeVersion = Runtime.class.getMethod("version").invoke(null);
version = (int) runtimeVersion.getClass().getMethod("major").invoke(runtimeVersion);
- } catch (Throwable ex) {
+ } catch (ReflectiveOperationException ex) {
version = BASE_VERSION;
}
RUNTIME_VERSION = version;
@@ -475,6 +483,7 @@
private boolean dead;
private int requests;
private int used;
+ private volatile int[] versions;
private volatile Reference<Manifest> manifest;
/** #141110: expensive to repeatedly look for them */
private final Set<String> nonexistentResources = Collections.synchronizedSet(new HashSet<String>());
@@ -607,14 +616,22 @@
@Override
protected byte[] readClass(String path) throws IOException {
try {
- if (isMultiRelease() && RUNTIME_VERSION != BASE_VERSION) {
- int ver = RUNTIME_VERSION;
- while (ver > BASE_VERSION) {
- byte[] data = archive.getData(this, "META-INF/versions/" + ver + "/" + path);
- if (data != null) {
- return data;
+ if (isMultiRelease() && RUNTIME_VERSION > BASE_VERSION) {
+ int[] vers = getVersions();
+ if (vers.length > 0) {
+ for (int i = vers.length - 1; i >= 0; i--) {
+ int version = vers[i];
+ if (version > RUNTIME_VERSION) {
+ continue;
+ }
+ if (version < BASE_VERSION) {
+ break;
+ }
+ byte[] data = archive.getData(this, "META-INF/versions/" + version + "/" + path);
+ if (data != null) {
+ return data;
+ }
}
- ver--;
}
}
return archive.getData(this, path);
@@ -623,7 +640,56 @@
throw ex;
}
}
-
+
+ private int[] getVersions() {
+ if (versions != null) {
+ return versions;
+ }
+ try {
+ JarFile src = getJarFile("versions");
+ Set<Integer> vers = new TreeSet<>();
+ Enumeration<JarEntry> en = src.entries();
+ while (en.hasMoreElements()) {
+ JarEntry je = en.nextElement();
+ if (je.isDirectory()) {
+ String itm = je.getName();
+ if (itm.startsWith("META-INF/versions/")) {
+ String res = itm.substring(18);
+ int idx = res.indexOf('/');
+ if (idx > 0 && idx == res.length() - 1) {
+ vers.add(Integer.parseInt(res.substring(0, idx)));
+ }
+ }
+ }
+ }
+ int[] ret = new int[vers.size()];
+ int i = 0;
+ for (Integer ver : vers) {
+ ret[i++] = ver;
+ }
+ versions = ret;
+ return ret;
+ } catch (ZipException x) { // Unix
+ if (warnedFiles.add(file)) {
+ LOGGER.log(Level.INFO, "Cannot open " + file, x);
+ dumpFiles(file, -1);
+ }
+ } catch (FileNotFoundException x) { // Windows
+ if (warnedFiles.add(file)) {
+ LOGGER.log(Level.INFO, "Cannot open " + file, x);
+ dumpFiles(file, -1);
+ }
+ } catch (IOException ioe) {
+ if (warnedFiles.add(file)) {
+ LOGGER.log(Level.WARNING, "problems with " + file, ioe);
+ dumpFiles(file, -1);
+ }
+ } finally {
+ releaseJarFile();
+ }
+ return new int[0];
+ }
+
@Override
public byte[] resource(String path) throws IOException {
if (nonexistentResources.contains(path)) {