From 2db13f12ae14385abca81f2c32e63e9295e5dbed Mon Sep 17 00:00:00 2001 From: Andy Clement Date: Fri, 10 May 2019 08:39:28 -0700 Subject: [PATCH] Final bits of AspectJ 1.9.4 --- docs/dist/doc/README-194.html | 46 ++++ docs/dist/doc/index.html | 1 + org.aspectj.lib/pom.xml | 2 +- org.eclipse.jdt.core/pom.xml | 4 +- pom.xml | 2 +- .../aspectj/weaver/bcel/ClassPathManager.java | 92 +++++--- .../weaver/bcel/ClasspathManagerTestCase.java | 214 ++++++++++++++++++ .../aspectj/weaver/bcel/JImageTestCase.java | 2 +- 8 files changed, 331 insertions(+), 32 deletions(-) create mode 100644 docs/dist/doc/README-194.html create mode 100644 weaver/src/test/java/org/aspectj/weaver/bcel/ClasspathManagerTestCase.java diff --git a/docs/dist/doc/README-194.html b/docs/dist/doc/README-194.html new file mode 100644 index 000000000..c133073e4 --- /dev/null +++ b/docs/dist/doc/README-194.html @@ -0,0 +1,46 @@ + + +AspectJ 1.9.4 Readme + + + + +
+© Copyright 2019 Contributors. +All rights reserved. +
+

The full list of resolved issues in 1.9.4 is available +here.

+ +

AspectJ 1.9.4 has a couple of important fixes in it: +

+ + +

Available: 1.9.4 available 10-May-2019

+ +

+ + + + + diff --git a/docs/dist/doc/index.html b/docs/dist/doc/index.html index 5d6805af5..68abf89d3 100644 --- a/docs/dist/doc/index.html +++ b/docs/dist/doc/index.html @@ -138,6 +138,7 @@ README's Changes and porting guide for AspectJ + 1.9.4, 1.9.3, 1.9.2, 1.9.1, diff --git a/org.aspectj.lib/pom.xml b/org.aspectj.lib/pom.xml index d90092aab..3e6091299 100644 --- a/org.aspectj.lib/pom.xml +++ b/org.aspectj.lib/pom.xml @@ -6,7 +6,7 @@ org.aspectj aspectj-parent - 1.9.3.BUILD-SNAPSHOT + 1.9.4.BUILD-SNAPSHOT .. diff --git a/org.eclipse.jdt.core/pom.xml b/org.eclipse.jdt.core/pom.xml index de9dcdd85..a0ad386f3 100644 --- a/org.eclipse.jdt.core/pom.xml +++ b/org.eclipse.jdt.core/pom.xml @@ -33,7 +33,7 @@ org.aspectj org.eclipse.jdt.core - 1.9.3.BUILD-SNAPSHOT + 1.9.4.BUILD-SNAPSHOT jar ${basedir}/jdtcore-for-aspectj.jar true @@ -49,7 +49,7 @@ org.aspectj org.eclipse.jdt.core - 1.9.3.BUILD-SNAPSHOT + 1.9.4.BUILD-SNAPSHOT jar ${basedir}/jdtcore-for-aspectj-src.zip true diff --git a/pom.xml b/pom.xml index 15f944cc8..7f8492b4e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - 1.9.3.BUILD-SNAPSHOT + 1.9.4.BUILD-SNAPSHOT UTF-8 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 states = new HashMap<>(); - private static FileSystem fs = null; + private JImageState state; - private final static Map fileCache = new SoftHashMap(); - - private final static Map packageCache = new HashMap(); - - 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 fileCache = new SoftHashMap(); + boolean packageCacheInitialized = false; + Map packageCache = new HashMap(); + + 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 env = new HashMap<>(); + env.put("java.home", jdkHome); + fs = FileSystems.newFileSystem(JRT_URI, env); + } else { + URLClassLoader loader = new URLClassLoader(new URL[] { jrtPath }); + HashMap 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 { @@ -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 roots = fs.getRootDirectories(); + if (!state.packageCacheInitialized) { + state.packageCacheInitialized = true; + Iterable 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 getPackageCache() { - return packageCache; + Map getPackageCache() { + return state.packageCache; } - static Map getFileCache() { - return fileCache; + Map 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 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 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 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 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 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 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 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 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 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 packageCache = JImageEntry.getPackageCache(); + Map packageCache = jie.getPackageCache(); assertTrue(packageCache.size()>0); // Note: seems to be about 1625 entries in it for Java9 Path path = packageCache.get("java/lang"); -- 2.39.5