aboutsummaryrefslogtreecommitdiffstats
path: root/weaver
diff options
context:
space:
mode:
authorAndy Clement <aclement@pivotal.io>2019-05-10 08:39:28 -0700
committerAndy Clement <aclement@pivotal.io>2019-05-10 08:39:28 -0700
commit2db13f12ae14385abca81f2c32e63e9295e5dbed (patch)
tree94753c20fba3375d4474c77d08d26ee5f0ffb70a /weaver
parentcef7d981ed3df324e37a20442f6bd0d1bdda3def (diff)
downloadaspectj-2db13f12ae14385abca81f2c32e63e9295e5dbed.tar.gz
aspectj-2db13f12ae14385abca81f2c32e63e9295e5dbed.zip
Final bits of AspectJ 1.9.4
Diffstat (limited to 'weaver')
-rw-r--r--weaver/src/main/java/org/aspectj/weaver/bcel/ClassPathManager.java92
-rw-r--r--weaver/src/test/java/org/aspectj/weaver/bcel/ClasspathManagerTestCase.java214
-rw-r--r--weaver/src/test/java/org/aspectj/weaver/bcel/JImageTestCase.java2
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");