diff options
author | Andy Clement <aclement@pivotal.io> | 2019-05-10 08:39:28 -0700 |
---|---|---|
committer | Andy Clement <aclement@pivotal.io> | 2019-05-10 08:39:28 -0700 |
commit | 2db13f12ae14385abca81f2c32e63e9295e5dbed (patch) | |
tree | 94753c20fba3375d4474c77d08d26ee5f0ffb70a /weaver | |
parent | cef7d981ed3df324e37a20442f6bd0d1bdda3def (diff) | |
download | aspectj-2db13f12ae14385abca81f2c32e63e9295e5dbed.tar.gz aspectj-2db13f12ae14385abca81f2c32e63e9295e5dbed.zip |
Final bits of AspectJ 1.9.4
Diffstat (limited to 'weaver')
3 files changed, 280 insertions, 28 deletions
diff --git a/weaver/src/main/java/org/aspectj/weaver/bcel/ClassPathManager.java b/weaver/src/main/java/org/aspectj/weaver/bcel/ClassPathManager.java index d617bbfa3..b903ee6de 100644 --- a/weaver/src/main/java/org/aspectj/weaver/bcel/ClassPathManager.java +++ b/weaver/src/main/java/org/aspectj/weaver/bcel/ClassPathManager.java @@ -17,7 +17,10 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.net.MalformedURLException; import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; @@ -105,9 +108,9 @@ public class ClassPathManager { return; } try { - if (lc.endsWith(LangUtil.JRT_FS)) { // Java9 - if (LangUtil.is19VMOrGreater()) { - entries.add(new JImageEntry()); + if (lc.endsWith(LangUtil.JRT_FS)) { // Java9+ + if (LangUtil.is18VMOrGreater()) { + entries.add(new JImageEntry(lc)); } } else { entries.add(new ZipFileEntry(f)); @@ -316,24 +319,59 @@ public class ClassPathManager { * helps reduce memory usage but still gives reasonably fast lookup performance. */ static class JImageEntry extends Entry { + + // Map from a JRT-FS file to the cache state for that file + private static Map<String, JImageState> states = new HashMap<>(); - private static FileSystem fs = null; + private JImageState state; - private final static Map<String, Path> fileCache = new SoftHashMap<String, Path>(); - - private final static Map<String, Path> packageCache = new HashMap<String, Path>(); - - private static boolean packageCacheInitialized = false; + // TODO memory management here - is it held onto too long when LTW? + static class JImageState { + private final String jrtFsPath; + private final FileSystem fs; + Map<String,Path> fileCache = new SoftHashMap<String, Path>(); + boolean packageCacheInitialized = false; + Map<String,Path> packageCache = new HashMap<String, Path>(); + + public JImageState(String jrtFsPath, FileSystem fs) { + this.jrtFsPath = jrtFsPath; + this.fs = fs; + } + } - public JImageEntry() { - if (fs == null) { - try { - fs = FileSystems.getFileSystem(JRT_URI); - } catch (Throwable t) { - throw new IllegalStateException("Unexpectedly unable to initialize a JRT filesystem", t); + public JImageEntry(String jrtFsPath) { + state = states.get(jrtFsPath); + if (state == null) { + synchronized (states) { + if (state == null) { + URL jrtPath = null; + try { + jrtPath = new File(jrtFsPath).toPath().toUri().toURL(); + } catch (MalformedURLException e) { + System.out.println("Unexpected problem processing "+jrtFsPath+" bad classpath entry? skipping:"+e.getMessage()); + return; + } + String jdkHome = new File(jrtFsPath).getParentFile().getParent(); + FileSystem fs = null; + try { + if (LangUtil.is19VMOrGreater()) { + HashMap<String, String> env = new HashMap<>(); + env.put("java.home", jdkHome); + fs = FileSystems.newFileSystem(JRT_URI, env); + } else { + URLClassLoader loader = new URLClassLoader(new URL[] { jrtPath }); + HashMap<String, ?> env = new HashMap<>(); + fs = FileSystems.newFileSystem(JRT_URI, env, loader); + } + state = new JImageState(jrtFsPath, fs); + states.put(jrtFsPath, state); + buildPackageMap(); + } catch (Throwable t) { + throw new IllegalStateException("Unexpectedly unable to initialize a JRT filesystem", t); + } + } } } - buildPackageMap(); } class PackageCacheBuilderVisitor extends SimpleFileVisitor<Path> { @@ -344,7 +382,7 @@ public class ClassPathManager { if (fnc > 3) { // There is a package name - e.g. /modules/java.base/java/lang/Object.class Path packagePath = file.subpath(2, fnc-1); // e.g. java/lang String packagePathString = packagePath.toString(); - packageCache.put(packagePathString, file.subpath(0, fnc-1)); // java/lang -> /modules/java.base/java/lang + state.packageCache.put(packagePathString, file.subpath(0, fnc-1)); // java/lang -> /modules/java.base/java/lang } } return FileVisitResult.CONTINUE; @@ -355,9 +393,9 @@ public class ClassPathManager { * Create a map from package names to the specific directory of the package members in the filesystem. */ private synchronized void buildPackageMap() { - if (!packageCacheInitialized) { - packageCacheInitialized = true; - Iterable<java.nio.file.Path> roots = fs.getRootDirectories(); + if (!state.packageCacheInitialized) { + state.packageCacheInitialized = true; + Iterable<java.nio.file.Path> roots = state.fs.getRootDirectories(); PackageCacheBuilderVisitor visitor = new PackageCacheBuilderVisitor(); try { for (java.nio.file.Path path : roots) { @@ -392,7 +430,7 @@ public class ClassPathManager { Path filePath = file.subpath(2, fnc); String filePathString = filePath.toString(); if (filePathString.equals(name)) { - fileCache.put(filePathString, file); + state.fileCache.put(filePathString, file); found = file; return FileVisitResult.TERMINATE; } @@ -414,7 +452,7 @@ public class ClassPathManager { @Override public ClassFile find(String name) throws IOException { String fileName = name.replace('.', '/') + ".class"; - Path file = fileCache.get(fileName); + Path file = state.fileCache.get(fileName); if (file == null) { // Check the packages map to see if we know about this package int idx = fileName.lastIndexOf('/'); @@ -426,7 +464,7 @@ public class ClassPathManager { String packageName = null; if (idx !=-1 ) { packageName = fileName.substring(0, idx); - packageStart = packageCache.get(packageName); + packageStart = state.packageCache.get(packageName); if (packageStart != null) { file = searchForFileAndCache(packageStart, fileName); } @@ -440,12 +478,12 @@ public class ClassPathManager { return cf; } - static Map<String, Path> getPackageCache() { - return packageCache; + Map<String, Path> getPackageCache() { + return state.packageCache; } - static Map<String, Path> getFileCache() { - return fileCache; + Map<String, Path> getFileCache() { + return state.fileCache; } } diff --git a/weaver/src/test/java/org/aspectj/weaver/bcel/ClasspathManagerTestCase.java b/weaver/src/test/java/org/aspectj/weaver/bcel/ClasspathManagerTestCase.java new file mode 100644 index 000000000..f4f84f168 --- /dev/null +++ b/weaver/src/test/java/org/aspectj/weaver/bcel/ClasspathManagerTestCase.java @@ -0,0 +1,214 @@ +/* ******************************************************************* + * Copyright (c) 2019 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * ******************************************************************/ +package org.aspectj.weaver.bcel; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +import org.aspectj.apache.bcel.classfile.ClassFormatException; +import org.aspectj.apache.bcel.classfile.ClassParser; +import org.aspectj.apache.bcel.classfile.JavaClass; +import org.aspectj.bridge.AbortException; +import org.aspectj.bridge.IMessage; +import org.aspectj.bridge.IMessage.Kind; +import org.aspectj.bridge.IMessageHandler; +import org.aspectj.util.LangUtil; +import org.aspectj.weaver.UnresolvedType; +import org.aspectj.weaver.bcel.ClassPathManager.ClassFile; + +import junit.framework.TestCase; + +/** + * Should run these tests 3 times on each JDK level (8, 9, 11). On each one 3 of the + * tests should pass indicating that JDK can successfully access system types in + * each JDK level. + * + * @author Andy Clement + */ +public class ClasspathManagerTestCase extends TestCase { + + // Works on my machine where all jvms under ~/jvms + private static String java18_rtjar = findJvm("j.*18.*","rt.jar"); + private static String java9_jrtfsjar = findJvm("j.*9.*","jrt-fs.jar");; + private static String java11_jrtfsjar = findJvm("j.*11.*","jrt-fs.jar");; + + private static String findJvm(String pattern, String jar) { + String start = System.getProperty("user.home")+"/jvms"; + for (File f: new File(start).listFiles()) { + if (f.isDirectory() && Pattern.matches(pattern, f.getName())) { + File result = walk(f, jar); + if (result !=null) { + System.out.println("For "+pattern+" found "+result.getAbsolutePath()); + return result.getAbsolutePath(); + } + } + } + return null; + } + + private static File walk(File dir, String jar) { + File[] fs = dir.listFiles(); + if (fs!=null) { + for (File f: fs) { + if (f.getName().equals(jar)) { + return f; + } else if (f.isDirectory()) { + File s = walk(f, jar); + if (s!=null) { + return s; + } + } + } + } + return null; + } + + public void testInstructions() { + System.out.println("This test is really only for standalone usage as it need executing on multiple JDK levels"); + } + + public void xtestSanity18accessing18RTJAR() throws IOException { + if (LangUtil.getVmVersion()>8) fail("Must be Java 8"); + List<String> classpath = new ArrayList<>(); + classpath.add(java18_rtjar); + ClassPathManager cpm = new ClassPathManager(classpath, new MH()); + ClassFile t = cpm.find(UnresolvedType.forSignature("Ljava/lang/Object;")); + assertNotNull(t); + } + + public void xtestJava18accessing11JRT() throws ClassFormatException, IOException { + if (LangUtil.getVmVersion()>8) fail("Must be Java 8"); + List<String> classpath = new ArrayList<>(); + classpath.add(java11_jrtfsjar); + ClassPathManager cpm = new ClassPathManager(classpath, new MH()); + ClassFile t = cpm.find(UnresolvedType.forSignature("Ljava/lang/String;")); + assertNotNull(t); + ClassParser classParser = new ClassParser(t.getInputStream(),t.getPath()); + JavaClass clazz = classParser.parse(); + // isBlank() exists on Java 11 + long c = Arrays.asList(clazz.getMethods()).stream().filter(m -> m.getName().equals("isBlank")).count(); + assertEquals(1,c); + } + + public void xtestJava18accessing19JRT() throws ClassFormatException, IOException { + if (LangUtil.getVmVersion()>8) fail("Must be Java 8"); + List<String> classpath = new ArrayList<>(); + classpath.add(java9_jrtfsjar); + ClassPathManager cpm = new ClassPathManager(classpath, new MH()); + ClassFile t = cpm.find(UnresolvedType.forSignature("Ljava/lang/String;")); + assertNotNull(t); + ClassParser classParser = new ClassParser(t.getInputStream(),t.getPath()); + JavaClass clazz = classParser.parse(); + // isBlank() exists on Java 11, but not on Java9 + long c = Arrays.asList(clazz.getMethods()).stream().filter(m -> m.getName().equals("isBlank")).count(); + assertEquals(0,c); + } + + + public void xtestSanity19accessing18RTJAR() throws IOException { + assertEquals(9.0,LangUtil.getVmVersion()); + List<String> classpath = new ArrayList<>(); + classpath.add(java18_rtjar); + ClassPathManager cpm = new ClassPathManager(classpath, new MH()); + ClassFile t = cpm.find(UnresolvedType.forSignature("Ljava/lang/Object;")); + assertNotNull(t); + } + + public void xtestJava19accessing11JRT() throws ClassFormatException, IOException { + assertEquals(9.0,LangUtil.getVmVersion()); + List<String> classpath = new ArrayList<>(); + classpath.add(java11_jrtfsjar); + ClassPathManager cpm = new ClassPathManager(classpath, new MH()); + ClassFile t = cpm.find(UnresolvedType.forSignature("Ljava/lang/String;")); + assertNotNull(t); + ClassParser classParser = new ClassParser(t.getInputStream(),t.getPath()); + JavaClass clazz = classParser.parse(); + // isBlank() exists on Java 11 + long c = Arrays.asList(clazz.getMethods()).stream().filter(m -> m.getName().equals("isBlank")).count(); + assertEquals(1,c); + } + + public void xtestJava19accessing19JRT() throws ClassFormatException, IOException { + assertEquals(9.0,LangUtil.getVmVersion()); + List<String> classpath = new ArrayList<>(); + classpath.add(java9_jrtfsjar); + ClassPathManager cpm = new ClassPathManager(classpath, new MH()); + ClassFile t = cpm.find(UnresolvedType.forSignature("Ljava/lang/String;")); + assertNotNull(t); + ClassParser classParser = new ClassParser(t.getInputStream(),t.getPath()); + JavaClass clazz = classParser.parse(); + // isBlank() exists on Java 11, but not on Java9 + long c = Arrays.asList(clazz.getMethods()).stream().filter(m -> m.getName().equals("isBlank")).count(); + assertEquals(0,c); + } + + public void xtestSanity11accessing18RTJAR() throws IOException { + assertEquals(11.0,LangUtil.getVmVersion()); + List<String> classpath = new ArrayList<>(); + classpath.add(java18_rtjar); + ClassPathManager cpm = new ClassPathManager(classpath, new MH()); + ClassFile t = cpm.find(UnresolvedType.forSignature("Ljava/lang/Object;")); + assertNotNull(t); + } + + public void xtestJava11accessing11JRT() throws ClassFormatException, IOException { + assertEquals(11.0,LangUtil.getVmVersion()); + List<String> classpath = new ArrayList<>(); + classpath.add(java11_jrtfsjar); + ClassPathManager cpm = new ClassPathManager(classpath, new MH()); + ClassFile t = cpm.find(UnresolvedType.forSignature("Ljava/lang/String;")); + assertNotNull(t); + ClassParser classParser = new ClassParser(t.getInputStream(),t.getPath()); + JavaClass clazz = classParser.parse(); + // isBlank() exists on Java 11 + long c = Arrays.asList(clazz.getMethods()).stream().filter(m -> m.getName().equals("isBlank")).count(); + assertEquals(1,c); + } + + public void xtestJava11accessing19JRT() throws ClassFormatException, IOException { + assertEquals(11.0,LangUtil.getVmVersion()); + List<String> classpath = new ArrayList<>(); + classpath.add(java9_jrtfsjar); + ClassPathManager cpm = new ClassPathManager(classpath, new MH()); + ClassFile t = cpm.find(UnresolvedType.forSignature("Ljava/lang/String;")); + assertNotNull(t); + ClassParser classParser = new ClassParser(t.getInputStream(),t.getPath()); + JavaClass clazz = classParser.parse(); + // isBlank() exists on Java 11, but not on Java9 + long c = Arrays.asList(clazz.getMethods()).stream().filter(m -> m.getName().equals("isBlank")).count(); + assertEquals(0,c); + } + + static class MH implements IMessageHandler { + + @Override + public boolean handleMessage(IMessage message) throws AbortException { + System.out.println(message); + return false; + } + + @Override + public boolean isIgnoring(Kind kind) { + return false; + } + + @Override + public void dontIgnore(Kind kind) { + } + + @Override + public void ignore(Kind kind) { + } + + } +} diff --git a/weaver/src/test/java/org/aspectj/weaver/bcel/JImageTestCase.java b/weaver/src/test/java/org/aspectj/weaver/bcel/JImageTestCase.java index 6e89c675c..abb8c08b2 100644 --- a/weaver/src/test/java/org/aspectj/weaver/bcel/JImageTestCase.java +++ b/weaver/src/test/java/org/aspectj/weaver/bcel/JImageTestCase.java @@ -70,7 +70,7 @@ public class JImageTestCase extends TestCase { if (!LangUtil.is19VMOrGreater()) return; JImageEntry jie = getJImageEntry(); - Map<String, Path> packageCache = JImageEntry.getPackageCache(); + Map<String, Path> packageCache = jie.getPackageCache(); assertTrue(packageCache.size()>0); // Note: seems to be about 1625 entries in it for Java9 Path path = packageCache.get("java/lang"); |