--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html> <head>
+<title>AspectJ 1.9.4 Readme</title>
+<style type="text/css">
+<!--
+ P { margin-left: 20px; }
+ PRE { margin-left: 20px; }
+ LI { margin-left: 20px; }
+ H4 { margin-left: 20px; }
+ H3 { margin-left: 10px; }
+-->
+</style>
+</head>
+
+<body>
+<div align="right"><small>
+© Copyright 2019 Contributors.
+All rights reserved.
+</small></div>
+<p>The full list of resolved issues in 1.9.4 is available
+<a href="https://bugs.eclipse.org/bugs/buglist.cgi?bug_status=RESOLVED&bug_status=VERIFIED&bug_status=CLOSED&f0=OP&f1=OP&f3=CP&f4=CP&j1=OR&list_id=16866879&product=AspectJ&query_format=advanced&target_milestone=1.9.4">here</a></h2>.</p>
+
+<p>AspectJ 1.9.4 has a couple of important fixes in it:
+<ul>
+<li>Due to the new maven build process being used to build release artifacts
+for the first time, there were errors in the aspectjweaver jar that affected
+the ability to use it on the command line as an agent,
+this is now fixed.
+<li>A number of users were noticing a ClassCastException problem, which I believe was due to trying to
+run AspectJ on one level of the JDK whilst targeting another. This can happen quite easily in eclipse
+if running your Eclipse on Java 8 but developing projects targeting Java 11.
+The class cast is because Java8 couldn't understand
+the packaging of system classes post Java9 and so couldn't find java.lang.Object. This has now all been
+tidied up and should work much better. More details in <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=546807">546807</a>,
+thanks to Denys Khanzhyiev for some tips on getting to the right solution.
+</ul>
+
+
+<p>Available: 1.9.4 available 10-May-2019</p>
+
+<br><br>
+
+
+<!-- ============================== -->
+</body>
+</html>
<tr> <td>README's
</td>
<td>Changes and porting guide for AspectJ
+ <a href="README-194.html">1.9.4</a>,
<a href="README-193.html">1.9.3</a>,
<a href="README-192.html">1.9.2</a>,
<a href="README-191.html">1.9.1</a>,
<parent>
<groupId>org.aspectj</groupId>
<artifactId>aspectj-parent</artifactId>
- <version>1.9.3.BUILD-SNAPSHOT</version>
+ <version>1.9.4.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<configuration>
<groupId>org.aspectj</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
- <version>1.9.3.BUILD-SNAPSHOT</version>
+ <version>1.9.4.BUILD-SNAPSHOT</version>
<packaging>jar</packaging>
<file>${basedir}/jdtcore-for-aspectj.jar</file>
<createChecksum>true</createChecksum>
<configuration>
<groupId>org.aspectj</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
- <version>1.9.3.BUILD-SNAPSHOT</version>
+ <version>1.9.4.BUILD-SNAPSHOT</version>
<packaging>jar</packaging>
<file>${basedir}/jdtcore-for-aspectj-src.zip</file>
<createChecksum>true</createChecksum>
<modelVersion>4.0.0</modelVersion>
<properties>
- <revision>1.9.3.BUILD-SNAPSHOT</revision>
+ <revision>1.9.4.BUILD-SNAPSHOT</revision>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
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;
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));
* 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> {
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;
* 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) {
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;
}
@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('/');
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);
}
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;
}
}
--- /dev/null
+/* *******************************************************************
+ * 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) {
+ }
+
+ }
+}
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");