Browse Source

Polish use of Unsafe

tags/V1_9_0_RC3
Andy Clement 6 years ago
parent
commit
b279bb8095
1 changed files with 63 additions and 80 deletions
  1. 63
    80
      loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java

+ 63
- 80
loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java View File

@@ -1,28 +1,32 @@
/*******************************************************************************
* Copyright (c) 2005 Contributors.
* Copyright (c) 2005, 2017 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://eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alexandre Vasseur initial implementation
* David Knibb weaving context enhancments
* John Kew (vmware) caching hook
*******************************************************************************/
package org.aspectj.weaver.loadtime;

import java.io.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.CodeSource;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.util.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;

import org.aspectj.bridge.AbortException;
import org.aspectj.bridge.Constants;
@@ -42,7 +46,10 @@ import org.aspectj.weaver.loadtime.definition.DocumentParser;
import org.aspectj.weaver.ltw.LTWWorld;
import org.aspectj.weaver.patterns.PatternParser;
import org.aspectj.weaver.patterns.TypePattern;
import org.aspectj.weaver.tools.*;
import org.aspectj.weaver.tools.GeneratedClassHandler;
import org.aspectj.weaver.tools.Trace;
import org.aspectj.weaver.tools.TraceFactory;
import org.aspectj.weaver.tools.WeavingAdaptor;
import org.aspectj.weaver.tools.cache.WeavedClassCache;

import sun.misc.Unsafe;
@@ -51,6 +58,8 @@ import sun.misc.Unsafe;
* @author Alexandre Vasseur
* @author Andy Clement
* @author Abraham Nevado
* @author David Knibb
* @author John Kew
*/
public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {

@@ -58,8 +67,8 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {

private boolean initialized;

private List<TypePattern> m_dumpTypePattern = new ArrayList<TypePattern>();
private boolean m_dumpBefore = false;
private List<TypePattern> dumpTypePattern = new ArrayList<TypePattern>();
private boolean dumpBefore = false;
private boolean dumpDirPerClassloader = false;

private boolean hasExcludes = false;
@@ -72,14 +81,14 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {

private boolean hasIncludes = false;
private List<TypePattern> includeTypePattern = new ArrayList<TypePattern>();
private List<String> m_includeStartsWith = new ArrayList<String>();
private List<String> includeStartsWith = new ArrayList<String>();
private List<String> includeExactName = new ArrayList<String>();
private boolean includeStar = false;

private List<TypePattern> m_aspectExcludeTypePattern = new ArrayList<TypePattern>();
private List<String> m_aspectExcludeStartsWith = new ArrayList<String>();
private List<TypePattern> m_aspectIncludeTypePattern = new ArrayList<TypePattern>();
private List<String> m_aspectIncludeStartsWith = new ArrayList<String>();
private List<TypePattern> aspectExcludeTypePattern = new ArrayList<TypePattern>();
private List<String> aspectExcludeStartsWith = new ArrayList<String>();
private List<TypePattern> aspectIncludeTypePattern = new ArrayList<TypePattern>();
private List<String> aspectIncludeStartsWith = new ArrayList<String>();

private StringBuffer namespace;
private IWeavingContext weavingContext;
@@ -158,7 +167,7 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {

this.generatedClassHandler = new SimpleGeneratedClassHandler(classLoader);

List definitions = weavingContext.getDefinitions(classLoader, this);
List<Definition> definitions = weavingContext.getDefinitions(classLoader, this);
if (definitions.isEmpty()) {
disable(); // TODO maw Needed to ensure messages are flushed
if (trace.isTraceEnabled()) {
@@ -237,7 +246,7 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
String file = System.getProperty("aj5.def", null);
if (file != null) {
info("using (-Daj5.def) " + file);
definitions.add(DocumentParser.parse((new File(file)).toURL()));
definitions.add(DocumentParser.parse((new File(file)).toURI().toURL()));
}
}

@@ -257,7 +266,7 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
if (!configFile.exists()) {
warn("configuration does not exist: " + nextDefinition);
} else {
definitions.add(DocumentParser.parse(configFile.toURL()));
definitions.add(DocumentParser.parse(configFile.toURI().toURL()));
}
} catch (MalformedURLException mue) {
error("malformed definition url: " + nextDefinition);
@@ -419,10 +428,10 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
for (Definition definition : definitions) {
for (String exclude : definition.getAspectExcludePatterns()) {
TypePattern excludePattern = new PatternParser(exclude).parseTypePattern();
m_aspectExcludeTypePattern.add(excludePattern);
aspectExcludeTypePattern.add(excludePattern);
fastMatchInfo = looksLikeStartsWith(exclude);
if (fastMatchInfo != null) {
m_aspectExcludeStartsWith.add(fastMatchInfo);
aspectExcludeStartsWith.add(fastMatchInfo);
}
}
}
@@ -433,10 +442,10 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
for (Definition definition : definitions) {
for (String include : definition.getAspectIncludePatterns()) {
TypePattern includePattern = new PatternParser(include).parseTypePattern();
m_aspectIncludeTypePattern.add(includePattern);
aspectIncludeTypePattern.add(includePattern);
fastMatchInfo = looksLikeStartsWith(include);
if (fastMatchInfo != null) {
m_aspectIncludeStartsWith.add(fastMatchInfo);
aspectIncludeStartsWith.add(fastMatchInfo);
}
}
}
@@ -591,7 +600,7 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
String include = iterator1.next();
fastMatchInfo = looksLikeStartsWith(include);
if (fastMatchInfo != null) {
m_includeStartsWith.add(fastMatchInfo);
includeStartsWith.add(fastMatchInfo);
} else if (include.equals("*")) {
includeStar = true;
} else if ((fastMatchInfo = looksLikeExactName(include)) != null) {
@@ -728,10 +737,10 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
for (Iterator<String> iterator1 = definition.getDumpPatterns().iterator(); iterator1.hasNext();) {
String dump = iterator1.next();
TypePattern pattern = new PatternParser(dump).parseTypePattern();
m_dumpTypePattern.add(pattern);
dumpTypePattern.add(pattern);
}
if (definition.shouldDumpBefore()) {
m_dumpBefore = true;
dumpBefore = true;
}
if (definition.createDumpDirPerClassloader()) {
dumpDirPerClassloader = true;
@@ -816,9 +825,9 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
}
}
boolean fastAccept = false;// defaults to false if no fast include
for (int i = 0; i < m_includeStartsWith.size(); i++) {
for (int i = 0; i < includeStartsWith.size(); i++) {
didSomeIncludeMatching = true;
fastAccept = fastClassName.startsWith(m_includeStartsWith.get(i));
fastAccept = fastClassName.startsWith(includeStartsWith.get(i));
if (fastAccept) {
return true;
}
@@ -854,9 +863,9 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
}
}
}
for (int i = 0; i < m_includeStartsWith.size(); i++) {
for (int i = 0; i < includeStartsWith.size(); i++) {
didSomeIncludeMatching = true;
boolean fastaccept = fastClassName.startsWith(m_includeStartsWith.get(i));
boolean fastaccept = fastClassName.startsWith(includeStartsWith.get(i));
if (fastaccept) {
return true;
}
@@ -879,21 +888,21 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
// this can be nice but very dangerous as well to change that
private boolean acceptAspect(String aspectClassName) {
// avoid ResolvedType if not needed
if (m_aspectExcludeTypePattern.isEmpty() && m_aspectIncludeTypePattern.isEmpty()) {
if (aspectExcludeTypePattern.isEmpty() && aspectIncludeTypePattern.isEmpty()) {
return true;
}

// still try to avoid ResolvedType if we have simple patterns
// EXCLUDE: if one match then reject
String fastClassName = aspectClassName.replace('/', '.').replace('.', '$');
for (int i = 0; i < m_aspectExcludeStartsWith.size(); i++) {
if (fastClassName.startsWith(m_aspectExcludeStartsWith.get(i))) {
for (int i = 0; i < aspectExcludeStartsWith.size(); i++) {
if (fastClassName.startsWith(aspectExcludeStartsWith.get(i))) {
return false;
}
}
// INCLUDE: if one match then accept
for (int i = 0; i < m_aspectIncludeStartsWith.size(); i++) {
if (fastClassName.startsWith(m_aspectIncludeStartsWith.get(i))) {
for (int i = 0; i < aspectIncludeStartsWith.size(); i++) {
if (fastClassName.startsWith(aspectIncludeStartsWith.get(i))) {
return true;
}
}
@@ -901,8 +910,7 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
// needs further analysis
ResolvedType classInfo = weaver.getWorld().resolve(UnresolvedType.forName(aspectClassName), true);
// exclude are "AND"ed
for (Iterator iterator = m_aspectExcludeTypePattern.iterator(); iterator.hasNext();) {
TypePattern typePattern = (TypePattern) iterator.next();
for (TypePattern typePattern: aspectExcludeTypePattern) {
if (typePattern.matchesStatically(classInfo)) {
// exclude match - skip
return false;
@@ -910,8 +918,7 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
}
// include are "OR"ed
boolean accept = true;// defaults to true if no include
for (Iterator iterator = m_aspectIncludeTypePattern.iterator(); iterator.hasNext();) {
TypePattern typePattern = (TypePattern) iterator.next();
for (TypePattern typePattern: aspectIncludeTypePattern) {
accept = typePattern.matchesStatically(classInfo);
if (accept) {
break;
@@ -924,19 +931,19 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
@Override
protected boolean shouldDump(String className, boolean before) {
// Don't dump before weaving unless asked to
if (before && !m_dumpBefore) {
if (before && !dumpBefore) {
return false;
}

// avoid ResolvedType if not needed
if (m_dumpTypePattern.isEmpty()) {
if (dumpTypePattern.isEmpty()) {
return false;
}

// TODO AV - optimize for className.startWith only
ResolvedType classInfo = weaver.getWorld().resolve(UnresolvedType.forName(className), true);
// dump
for (Iterator<TypePattern> iterator = m_dumpTypePattern.iterator(); iterator.hasNext();) {
for (Iterator<TypePattern> iterator = dumpTypePattern.iterator(); iterator.hasNext();) {
TypePattern typePattern = iterator.next();
if (typePattern.matchesStatically(classInfo)) {
// dump match
@@ -995,11 +1002,9 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
*/
public void flushGeneratedClasses() {
// System.err.println("? ClassLoaderWeavingAdaptor.flushGeneratedClasses() generatedClasses=" + generatedClasses);
generatedClasses = new HashMap();
generatedClasses = new HashMap<>();
}

private Method defineClassMethod;
private Method defineClassWithProtectionDomainMethod;
private Unsafe unsafe;

private Unsafe getUnsafe() throws NoSuchFieldException, IllegalAccessException {
@@ -1017,26 +1022,15 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
}
Object clazz = null;
debug("generating class '" + name + "'");

try {
// loader.getClass().getProtectionDomain()
// ProtectionDomain pd = new ProtectionDomain(new CodeSource(new URL("",""),(Certificate[])null), new Permissions());
clazz = getUnsafe().defineClass(name, bytes, 0, bytes.length, loader, null);
// if (defineClassMethod == null) {
// defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass", new Class[] { String.class,
// bytes.getClass(), int.class, int.class });
// }
// defineClassMethod.setAccessible(true);
// clazz = defineClassMethod.invoke(loader, new Object[] { name, bytes, new Integer(0), new Integer(bytes.length) });
// } catch (InvocationTargetException e) {
// if (e.getTargetException() instanceof LinkageError) {
// warn("define generated class failed", e.getTargetException());
// // is already defined (happens for X$ajcMightHaveAspect interfaces since aspects are reweaved)
// // TODO maw I don't think this is OK and
// } else {
// warn("define generated class failed", e.getTargetException());
// }
} catch (LinkageError le) {
// likely thrown due to defining something that already exists?
// Old comments from before moving to Unsafe.defineClass():
// is already defined (happens for X$ajcMightHaveAspect interfaces since aspects are reweaved)
// TODO maw I don't think this is OK and
} catch (Exception e) {
e.printStackTrace(System.err);
warn("define generated class failed", e);
}

@@ -1052,23 +1046,12 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
Object clazz = null;
debug("generating class '" + name + "'");
try {
// // System.out.println(">> Defining with protection domain " + name + " pd=" + protectionDomain);
// if (defineClassWithProtectionDomainMethod == null) {
// defineClassWithProtectionDomainMethod = ClassLoader.class.getDeclaredMethod("defineClass", new Class[] {
// String.class, bytes.getClass(), int.class, int.class, ProtectionDomain.class });
// }
// defineClassWithProtectionDomainMethod.setAccessible(true);
// clazz = defineClassWithProtectionDomainMethod.invoke(loader, new Object[] { name, bytes, Integer.valueOf(0),
// new Integer(bytes.length), protectionDomain });
getUnsafe().defineClass(name, bytes, 0, bytes.length, loader, protectionDomain);
// } catch (InvocationTargetException e) {
// if (e.getTargetException() instanceof LinkageError) {
// warn("define generated class failed", e.getTargetException());
// // is already defined (happens for X$ajcMightHaveAspect interfaces since aspects are reweaved)
// // TODO maw I don't think this is OK and
// } else {
// warn("define generated class failed", e.getTargetException());
// }
} catch (LinkageError le) {
// likely thrown due to defining something that already exists?
// Old comments from before moving to Unsafe.defineClass():
// is already defined (happens for X$ajcMightHaveAspect interfaces since aspects are reweaved)
// TODO maw I don't think this is OK and
} catch (Exception e) {
warn("define generated class failed", e);
}

Loading…
Cancel
Save