diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 00000000..73610e73
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,17 @@
+language: generic
+
+jdk:
+ - openjdk6
+ - oraclejdk6
+
+cache:
+ directories:
+ - "$HOME/.m2/repository"
+
+script:
+ - cd bin
+ - ./sandbox-packages.sh
+ - cd ..
+
+after_success:
+ - bash <(curl -s https://codecov.io/bash)
\ No newline at end of file
diff --git a/README.md b/README.md
index c2bfe735..5705b11e 100755
--- a/README.md
+++ b/README.md
@@ -1,4 +1,11 @@
## ![BANNER](https://github.com/alibaba/jvm-sandbox/wiki/img/BANNER.png)
+
+[![Build Status](https://travis-ci.org/alibaba/jvm-sandbox.svg?branch=develop-for-20181027)](https://travis-ci.org/alibaba/jvm-sandbox)
+[![codecov](https://codecov.io/gh/alibaba/jvm-sandbox/branch/develop-for-20181027/graph/badge.svg)](https://codecov.io/gh/alibaba/jvm-sandbox)
+![license](https://img.shields.io/github/license/alibaba/arthas.svg)
+[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/alibaba/jvm-sandbox.svg)](http://isitmaintained.com/project/alibaba/jvm-sandbox "Average time to resolve an issue")
+[![Percentage of issues still open](http://isitmaintained.com/badge/open/alibaba/jvm-sandbox.svg)](http://isitmaintained.com/project/alibaba/jvm-sandbox "Percentage of issues still open")
+
> JVM沙箱容器,一种JVM的非侵入式运行期AOP解决方案
> Real - time non-invasive AOP framework container based on JVM
diff --git a/bin/sandbox-packages.sh b/bin/sandbox-packages.sh
index fcd9205f..92ee26cf 100755
--- a/bin/sandbox-packages.sh
+++ b/bin/sandbox-packages.sh
@@ -14,7 +14,7 @@ exit_on_err()
}
# maven package the sandbox
-mvn clean package -Dmaven.test.skip=false -f ../pom.xml \
+mvn clean cobertura:cobertura package -Dmaven.test.skip=false -f ../pom.xml \
|| exit_on_err 1 "package sandbox failed."
# reset the target dir
diff --git a/pom.xml b/pom.xml
index 459f02e9..bbaddbe5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,14 +4,14 @@
com.alibaba.jvm.sandbox
sandbox
- 1.1.0
+ 1.1.1-SNAPSHOT
pom
sandbox ${sandbox.version}
UTF-8
- 1.1.0
+ 1.1.1-SNAPSHOT
diff --git a/sandbox-agent/pom.xml b/sandbox-agent/pom.xml
index 5b1519db..c40e5b6e 100755
--- a/sandbox-agent/pom.xml
+++ b/sandbox-agent/pom.xml
@@ -6,7 +6,7 @@
com.alibaba.jvm.sandbox
sandbox
- 1.1.0
+ 1.1.1-SNAPSHOT
sandbox-agent
sandbox-agent ${sandbox.version}
diff --git a/sandbox-api/pom.xml b/sandbox-api/pom.xml
index 63f7abc7..d5b869fc 100755
--- a/sandbox-api/pom.xml
+++ b/sandbox-api/pom.xml
@@ -6,7 +6,7 @@
com.alibaba.jvm.sandbox
sandbox
- 1.1.0
+ 1.1.1-SNAPSHOT
sandbox-api
sandbox-api ${sandbox.version}
diff --git a/sandbox-common-api/pom.xml b/sandbox-common-api/pom.xml
index 8e476bd4..13b7e8ac 100644
--- a/sandbox-common-api/pom.xml
+++ b/sandbox-common-api/pom.xml
@@ -6,7 +6,7 @@
sandbox
com.alibaba.jvm.sandbox
- 1.1.0
+ 1.1.1-SNAPSHOT
sandbox-common-api
sandbox-common-api ${sandbox.version}
diff --git a/sandbox-core/pom.xml b/sandbox-core/pom.xml
index 550b3b1e..1eb69a21 100755
--- a/sandbox-core/pom.xml
+++ b/sandbox-core/pom.xml
@@ -6,7 +6,7 @@
com.alibaba.jvm.sandbox
sandbox
- 1.1.0
+ 1.1.1-SNAPSHOT
sandbox-core
sandbox-core ${sandbox.version}
@@ -134,17 +134,17 @@
org.ow2.asm
asm
- 6.0
+ 7.0
org.ow2.asm
asm-commons
- 6.0
+ 7.0
org.ow2.asm
asm-util
- 6.0
+ 7.0
org.apache.commons
diff --git a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/enhance/EventEnhancer.java b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/enhance/EventEnhancer.java
index e68283f2..b035cc16 100755
--- a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/enhance/EventEnhancer.java
+++ b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/enhance/EventEnhancer.java
@@ -17,6 +17,7 @@
import static org.objectweb.asm.ClassReader.EXPAND_FRAMES;
import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
import static org.objectweb.asm.ClassWriter.COMPUTE_MAXS;
+import static org.objectweb.asm.Opcodes.ASM7;
/**
* 事件代码增强器
@@ -90,7 +91,7 @@ private byte[] weavingEvent(final ClassLoader targetClassLoader,
final int targetClassLoaderObjectID = ObjectIDs.instance.identity(targetClassLoader);
cr.accept(
new EventWeaver(
- Opcodes.ASM6, cw, namespace, listenerId,
+ ASM7, cw, namespace, listenerId,
targetClassLoaderObjectID,
cr.getClassName(),
signCodes,
diff --git a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/enhance/weaver/asm/ReWriteMethod.java b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/enhance/weaver/asm/ReWriteMethod.java
index 3e73fee2..211911a6 100755
--- a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/enhance/weaver/asm/ReWriteMethod.java
+++ b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/enhance/weaver/asm/ReWriteMethod.java
@@ -18,7 +18,7 @@ public class ReWriteMethod extends AdviceAdapter implements Opcodes, AsmTypes, A
* Creates a new {@link AdviceAdapter}.
*
* @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4} or {@link Opcodes#ASM6}.
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM7}.
* @param mv the method visitor to which this adapter delegates calls.
* @param access the method's access flags (see {@link Opcodes}).
* @param name the method's name.
diff --git a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/server/jetty/JettyCoreServer.java b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/server/jetty/JettyCoreServer.java
index 4acb9e38..14f5b705 100755
--- a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/server/jetty/JettyCoreServer.java
+++ b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/server/jetty/JettyCoreServer.java
@@ -69,6 +69,7 @@ public boolean isBind() {
@Override
public void unbind() throws IOException {
try {
+
initializer.destroyProcess(new Initializer.Processor() {
@Override
public void process() throws Throwable {
@@ -86,6 +87,10 @@ public void process() throws Throwable {
httpServer.destroy();
logger.info("{} was destroyed.", this);
+ // 关闭对象池
+ EventListenerHandlers.getSingleton().getEventPool().close();
+ logger.info("{} was closed the Event-Pool!", this);
+
} catch (Throwable cause) {
logger.warn("{} unBind failed.", this, cause);
throw new IOException("unBind failed.", cause);
diff --git a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/EventPool.java b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/EventPool.java
index 54b17838..9fc39551 100755
--- a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/EventPool.java
+++ b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/EventPool.java
@@ -28,6 +28,18 @@ public EventPool() {
this.isEnable = this.pool != null;
}
+ /**
+ * 关闭并清理对象池
+ *
+ * 修复问题:#108
+ *
+ */
+ public void close() {
+ if (null != pool) {
+ pool.close();
+ }
+ }
+
private KeyedObjectPool createEventPool() {
final CoreConfigure cfg = CoreConfigure.getInstance();
if (cfg.isEventPoolEnable()) {
diff --git a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/BehaviorStructure.java b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/BehaviorStructure.java
index 954ae250..2048ef06 100644
--- a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/BehaviorStructure.java
+++ b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/BehaviorStructure.java
@@ -28,29 +28,6 @@ public class BehaviorStructure extends MemberStructure {
private final List exceptionTypeClassStructures;
private final List annotationTypeClassStructures;
- private final LazyGet signCodeLazyGet = new LazyGet() {
- @Override
- protected String initialValue() {
- return String.format("%s#%s(%s)",
- getDeclaringClassStructure().getJavaClassName(),
- getName(),
- join(takeJavaClassNames(getParameterTypeClassStructures()), ",")
- );
- }
- };
-
- private final LazyGet toStringLazyGet = new LazyGet() {
- @Override
- protected String initialValue() {
- return String.format("%s:[%s]:%s:%s",
- getReturnTypeClassStructure().getJavaClassName(),
- join(takeJavaClassNames(getAnnotationTypeClassStructures()), ","),
- getSignCode(),
- join(takeJavaClassNames(getExceptionTypeClassStructures()), ",")
- );
- }
- };
-
BehaviorStructure(final Access access,
final String name,
final ClassStructure declaringClassStructure,
@@ -109,6 +86,18 @@ private Collection takeJavaClassNames(final Collection c
return javaClassNames;
}
+
+ private final LazyGet signCodeLazyGet = new LazyGet() {
+ @Override
+ protected String initialValue() {
+ return String.format("%s#%s(%s)",
+ getDeclaringClassStructure().getJavaClassName(),
+ getName(),
+ join(takeJavaClassNames(getParameterTypeClassStructures()), ",")
+ );
+ }
+ };
+
/**
* 获取行为签名
*
@@ -121,6 +110,18 @@ public String getSignCode() {
return signCodeLazyGet.get();
}
+ private final LazyGet toStringLazyGet = new LazyGet() {
+ @Override
+ protected String initialValue() {
+ return String.format("%s:[%s]:%s:%s",
+ getReturnTypeClassStructure().getJavaClassName(),
+ join(takeJavaClassNames(getAnnotationTypeClassStructures()), ","),
+ getSignCode(),
+ join(takeJavaClassNames(getExceptionTypeClassStructures()), ",")
+ );
+ }
+ };
+
@Override
public String toString() {
// %s[0] : return-type
diff --git a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/ClassStructureImplByAsm.java b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/ClassStructureImplByAsm.java
index 8ca59287..16e24508 100644
--- a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/ClassStructureImplByAsm.java
+++ b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/ClassStructureImplByAsm.java
@@ -6,6 +6,7 @@
import com.alibaba.jvm.sandbox.core.util.collection.Pair;
import com.alibaba.jvm.sandbox.core.util.matcher.structure.PrimitiveClassStructure.Primitive;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
import org.objectweb.asm.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -13,6 +14,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
import static com.alibaba.jvm.sandbox.core.util.SandboxStringUtils.toInternalClassName;
import static com.alibaba.jvm.sandbox.core.util.SandboxStringUtils.toJavaClassName;
@@ -27,7 +29,7 @@ class AccessImplByAsm implements Access {
private final int access;
- AccessImplByAsm(int access) {
+ AccessImplByAsm(final int access) {
this.access = access;
}
@@ -61,7 +63,9 @@ public boolean isProtected() {
@Override
public boolean isStatic() {
- return BitUtils.isIn(getAccess(), ACC_STATIC);
+ // 隐性的Java语法约束:如果是接口类型,就一定是静态的
+ return isInterface()
+ || BitUtils.isIn(getAccess(), ACC_STATIC);
}
@Override
@@ -165,23 +169,30 @@ class PrimitiveClassStructure extends EmptyClassStructure {
}
public enum Primitive {
- BOOLEAN("boolean"),
- CHAR("char"),
- BYTE("byte"),
- INT("int"),
- SHORT("short"),
- LONG("long"),
- FLOAT("float"),
- DOUBLE("double"),
- VOID("void");
+ BOOLEAN("boolean", boolean.class),
+ CHAR("char", char.class),
+ BYTE("byte", byte.class),
+ INT("int", int.class),
+ SHORT("short", short.class),
+ LONG("long", long.class),
+ FLOAT("float", float.class),
+ DOUBLE("double", double.class),
+ VOID("void", void.class);
private final String type;
+ private final Access access;
- Primitive(final String type) {
+ Primitive(final String type, final Class> clazz) {
this.type = type;
+ this.access = new AccessImplByJDKClass(clazz);
}
}
+ @Override
+ public Access getAccess() {
+ return primitive.access;
+ }
+
@Override
public String getJavaClassName() {
return primitive.type;
@@ -208,10 +219,7 @@ class ArrayClassStructure extends EmptyClassStructure {
@Override
public String getJavaClassName() {
- return new StringBuilder()
- .append(elementClassStructure.getJavaClassName())
- .append("[]")
- .toString();
+ return elementClassStructure.getJavaClassName() + "[]";
}
}
@@ -227,16 +235,35 @@ public class ClassStructureImplByAsm extends FamilyClassStructure {
private final ClassLoader loader;
private final Access access;
- public ClassStructureImplByAsm(final InputStream classInputStream,
+ ClassStructureImplByAsm(final InputStream classInputStream,
final ClassLoader loader) throws IOException {
this(IOUtils.toByteArray(classInputStream), loader);
}
- public ClassStructureImplByAsm(final byte[] classByteArray,
+ ClassStructureImplByAsm(final byte[] classByteArray,
final ClassLoader loader) {
this.classReader = new ClassReader(classByteArray);
this.loader = loader;
- this.access = new AccessImplByAsm(this.classReader.getAccess());
+ this.access = fixAccess();
+ }
+
+ /**
+ * 修正内部类时候Access的获取策略差异
+ *
+ * @return 修正后的Access
+ */
+ private Access fixAccess() {
+ final AtomicInteger accessRef = new AtomicInteger(this.classReader.getAccess());
+ final String internalClassName = this.classReader.getClassName();
+ this.classReader.accept(new ClassVisitor(ASM7) {
+ @Override
+ public void visitInnerClass(String name, String outerName, String innerName, int access) {
+ if (StringUtils.equals(name, internalClassName)) {
+ accessRef.set(access);
+ }
+ }
+ }, ASM7);
+ return new AccessImplByAsm(accessRef.get());
}
private boolean isBootstrapClassLoader() {
@@ -283,6 +310,7 @@ private ClassStructure newInstance(final String javaClassName) {
if (classStructureCache.containsKey(pair)) {
return classStructureCache.get(pair);
} else {
+
final InputStream is = getResourceAsStream(internalClassNameToResourceName(toInternalClassName(javaClassName)));
if (null != is) {
try {
@@ -300,19 +328,6 @@ private ClassStructure newInstance(final String javaClassName) {
}
}
-// // 是个普通Java类型
-// final InputStream is = getResourceAsStream(internalClassNameToResourceName(toInternalClassName(javaClassName)));
-// if (null != is) {
-// try {
-// return new ClassStructureImplByAsm(is, loader);
-// } catch (Throwable cause) {
-// // ignore
-// logger.warn("new instance class structure by using ASM failed, will return null. class={};loader={};",
-// javaClassName, loader, cause);
-// } finally {
-// IOUtils.closeQuietly(is);
-// }
-// }
// 出现异常或者找不到
return null;
}
@@ -350,8 +365,12 @@ public ClassLoader getClassLoader() {
private final LazyGet superClassStructureLazyGet
= new LazyGet() {
@Override
- protected ClassStructure initialValue() throws Throwable {
- return newInstance(toJavaClassName(classReader.getSuperName()));
+ protected ClassStructure initialValue() {
+ final String superInternalClassName = classReader.getSuperName();
+ if (StringUtils.equals("java/lang/Object", superInternalClassName)) {
+ return null;
+ }
+ return newInstance(toJavaClassName(superInternalClassName));
}
};
@@ -363,7 +382,7 @@ public ClassStructure getSuperClassStructure() {
private final LazyGet> interfaceClassStructuresLazyGet
= new LazyGet>() {
@Override
- protected List initialValue() throws Throwable {
+ protected List initialValue() {
return newInstances(classReader.getInterfaces());
}
};
@@ -376,9 +395,9 @@ public List getInterfaceClassStructures() {
private final LazyGet> annotationTypeClassStructuresLazyGet
= new LazyGet>() {
@Override
- protected List initialValue() throws Throwable {
+ protected List initialValue() {
final List annotationTypeClassStructures = new ArrayList();
- accept(new ClassVisitor(ASM6) {
+ accept(new ClassVisitor(ASM7) {
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
@@ -405,9 +424,9 @@ public List getAnnotationTypeClassStructures() {
private final LazyGet> behaviorStructuresLazyGet
= new LazyGet>() {
@Override
- protected List initialValue() throws Throwable {
+ protected List initialValue() {
final List behaviorStructures = new ArrayList();
- accept(new ClassVisitor(ASM6) {
+ accept(new ClassVisitor(ASM7) {
@Override
public MethodVisitor visitMethod(final int access,
@@ -415,7 +434,14 @@ public MethodVisitor visitMethod(final int access,
final String desc,
final String signature,
final String[] exceptions) {
- return new MethodVisitor(ASM6, super.visitMethod(access, name, desc, signature, exceptions)) {
+
+ // 修复ASM会把列入正常方法中的问题
+ // 实际上这个方法并不会参与到任何的逻辑判断
+ if (StringUtils.equals("", name)) {
+ return super.visitMethod(access, name, desc, signature, exceptions);
+ }
+
+ return new MethodVisitor(ASM7, super.visitMethod(access, name, desc, signature, exceptions)) {
private final Type methodType = Type.getMethodType(desc);
private final List annotationTypeClassStructures = new ArrayList();
@@ -488,4 +514,10 @@ public Access getAccess() {
return access;
}
+ @Override
+ public String toString() {
+ return "ClassStructureImplByAsm{" +
+ "javaClassName='" + getJavaClassName() + '\'' +
+ '}';
+ }
}
diff --git a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/ClassStructureImplByJDK.java b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/ClassStructureImplByJDK.java
index 7cded9d4..764676a5 100644
--- a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/ClassStructureImplByJDK.java
+++ b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/ClassStructureImplByJDK.java
@@ -8,6 +8,7 @@
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
abstract class ModifierAccess implements Access {
@@ -136,20 +137,19 @@ private List newInstances(final Class[] classArray) {
@Override
public String getJavaClassName() {
- if (null != javaClassName) {
- return javaClassName;
- }
-
- return javaClassName = clazz.isArray()
- ? clazz.getCanonicalName()
- : clazz.getName();
+ return null != javaClassName
+ ? javaClassName
+ : (javaClassName = getJavaClassName(clazz));
+ }
-// final String canonicalName = clazz.getCanonicalName();
-// return javaClassName = StringUtils.isEmpty(canonicalName)
-// ? clazz.getName()
-// : canonicalName;
+ private String getJavaClassName(Class> clazz) {
+ if (clazz.isArray()) {
+ return getJavaClassName(clazz.getComponentType()) + "[]";
+ }
+ return clazz.getName();
}
+
@Override
public ClassLoader getClassLoader() {
return clazz.getClassLoader();
@@ -157,7 +157,10 @@ public ClassLoader getClassLoader() {
@Override
public ClassStructure getSuperClassStructure() {
- return newInstance(clazz.getSuperclass());
+ // 过滤掉Object.class
+ return Object.class.equals(clazz.getSuperclass())
+ ? null
+ : newInstance(clazz.getSuperclass());
}
@Override
@@ -183,8 +186,8 @@ private Class[] getAnnotationTypeArray(final Annotation[] annotationArray) {
private final LazyGet> annotationTypeClassStructuresLazyGet
= new LazyGet>() {
@Override
- protected List initialValue() throws Throwable {
- return newInstances(getAnnotationTypeArray(clazz.getDeclaredAnnotations()));
+ protected List initialValue() {
+ return Collections.unmodifiableList(newInstances(getAnnotationTypeArray(clazz.getDeclaredAnnotations())));
}
};
@@ -228,7 +231,7 @@ protected List initialValue() {
for (final Method method : clazz.getDeclaredMethods()) {
behaviorStructures.add(newBehaviorStructure(method));
}
- return behaviorStructures;
+ return Collections.unmodifiableList(behaviorStructures);
}
};
@@ -242,5 +245,8 @@ public Access getAccess() {
return new AccessImplByJDKClass(clazz);
}
-
+ @Override
+ public String toString() {
+ return "ClassStructureImplByJDK{" + "javaClassName='" + javaClassName + '\'' + '}';
+ }
}
diff --git a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/FamilyClassStructure.java b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/FamilyClassStructure.java
index f269eedc..a639d815 100644
--- a/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/FamilyClassStructure.java
+++ b/sandbox-core/src/main/java/com/alibaba/jvm/sandbox/core/util/matcher/structure/FamilyClassStructure.java
@@ -4,7 +4,6 @@
import java.lang.annotation.Inherited;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
@@ -13,7 +12,7 @@ public abstract class FamilyClassStructure implements ClassStructure {
private final LazyGet> familyInterfaceClassStructuresLazyGet
= new LazyGet>() {
@Override
- protected Set initialValue() throws Throwable {
+ protected Set initialValue() {
final Set familyInterfaceClassStructures = new HashSet();
for (final ClassStructure interfaceClassStructure : getInterfaceClassStructures()) {
// 1. 先加自己声明的接口
@@ -21,6 +20,13 @@ protected Set initialValue() throws Throwable {
// 2. 再加接口所声明的祖先(接口继承)
familyInterfaceClassStructures.addAll(interfaceClassStructure.getFamilyInterfaceClassStructures());
}
+
+ // BUGFIX: 修复获取家族接口类结构时忘记考虑自身父类的情况
+ // AUTHOR: oldmanpushcart@gmail.com
+ for (final ClassStructure superClassStructure : getFamilySuperClassStructures()) {
+ familyInterfaceClassStructures.addAll(superClassStructure.getFamilyInterfaceClassStructures());
+ }
+
return familyInterfaceClassStructures;
}
};
@@ -34,7 +40,7 @@ public Set getFamilyInterfaceClassStructures() {
private final LazyGet> familyTypeClassStructuresLazyGet
= new LazyGet>() {
@Override
- protected Set initialValue() throws Throwable {
+ protected Set initialValue() {
final Set familyClassStructures = new LinkedHashSet();
// 注入家族类&家族类所声明的家族接口
@@ -71,25 +77,24 @@ private static boolean isInheritedAnnotationType(ClassStructure classStructure)
}
// 过滤掉没有@Inherited标注的Annotation,因为他们不能继承
- private Set filterInheritedAnnotationTypeClassStructure(final Set classStructures) {
- final Iterator itCs = new HashSet(classStructures).iterator();
- while (itCs.hasNext()) {
- final ClassStructure annotationTypeClassStructure = itCs.next();
- if (!isInheritedAnnotationType(annotationTypeClassStructure)) {
- itCs.remove();
+ private Set newSetWithFilterInheritedAnnotationTypeClassStructure(final Set classStructures) {
+ final Set inheritedAnnotationSet = new LinkedHashSet();
+ for (final ClassStructure classStructure : classStructures) {
+ if (isInheritedAnnotationType(classStructure)) {
+ inheritedAnnotationSet.add(classStructure);
}
}
- return classStructures;
+ return inheritedAnnotationSet;
}
private final LazyGet> familyAnnotationTypeClassStructuresLazyGet
= new LazyGet>() {
@Override
- protected Set initialValue() throws Throwable {
+ protected Set initialValue() {
final Set familyAnnotationTypeClassStructures = new HashSet(getAnnotationTypeClassStructures());
for (final ClassStructure familyClassStructure : getFamilyTypeClassStructures()) {
familyAnnotationTypeClassStructures.addAll(
- filterInheritedAnnotationTypeClassStructure(
+ newSetWithFilterInheritedAnnotationTypeClassStructure(
familyClassStructure.getFamilyAnnotationTypeClassStructures()
)
);//addAll
@@ -106,7 +111,7 @@ public Set getFamilyAnnotationTypeClassStructures() {
private final LazyGet> familySuperClassStructuresLazyGet
= new LazyGet>() {
@Override
- protected LinkedHashSet initialValue() throws Throwable {
+ protected LinkedHashSet initialValue() {
final LinkedHashSet familySuperClassStructures = new LinkedHashSet();
final ClassStructure superClassStructure = getSuperClassStructure();
if (null != superClassStructure) {
diff --git a/sandbox-debug-module/pom.xml b/sandbox-debug-module/pom.xml
index 6400d12f..50ab0631 100755
--- a/sandbox-debug-module/pom.xml
+++ b/sandbox-debug-module/pom.xml
@@ -6,7 +6,7 @@
com.alibaba.jvm.sandbox
sandbox-module-starter
- 1.1.0
+ 1.1.1-SNAPSHOT
../sandbox-module-starter/pom.xml
sandbox-debug-module
diff --git a/sandbox-mgr-module/pom.xml b/sandbox-mgr-module/pom.xml
index 0b90c283..5242785d 100755
--- a/sandbox-mgr-module/pom.xml
+++ b/sandbox-mgr-module/pom.xml
@@ -6,7 +6,7 @@
com.alibaba.jvm.sandbox
sandbox-module-starter
- 1.1.0
+ 1.1.1-SNAPSHOT
../sandbox-module-starter/pom.xml
sandbox-mgr-module
diff --git a/sandbox-mgr-module/src/main/java/com/alibaba/jvm/sandbox/module/mgr/ControlModule.java b/sandbox-mgr-module/src/main/java/com/alibaba/jvm/sandbox/module/mgr/ControlModule.java
index 32f70180..32986785 100644
--- a/sandbox-mgr-module/src/main/java/com/alibaba/jvm/sandbox/module/mgr/ControlModule.java
+++ b/sandbox-mgr-module/src/main/java/com/alibaba/jvm/sandbox/module/mgr/ControlModule.java
@@ -7,15 +7,12 @@
import com.alibaba.jvm.sandbox.api.resource.ConfigInfo;
import com.alibaba.jvm.sandbox.api.resource.ModuleManager;
import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
diff --git a/sandbox-mgr-provider/pom.xml b/sandbox-mgr-provider/pom.xml
index 0532825e..4f0160d7 100644
--- a/sandbox-mgr-provider/pom.xml
+++ b/sandbox-mgr-provider/pom.xml
@@ -6,7 +6,7 @@
sandbox
com.alibaba.jvm.sandbox
- 1.1.0
+ 1.1.1-SNAPSHOT
sandbox-mgr-provider
sandbox-mgr-provider ${sandbox.version}
diff --git a/sandbox-module-starter/pom.xml b/sandbox-module-starter/pom.xml
index 4b163eb4..d9495278 100644
--- a/sandbox-module-starter/pom.xml
+++ b/sandbox-module-starter/pom.xml
@@ -6,7 +6,7 @@
com.alibaba.jvm.sandbox
sandbox
- 1.1.0
+ 1.1.1-SNAPSHOT
sandbox-module-starter
sandbox-module-starter ${sandbox.version}
diff --git a/sandbox-provider-api/pom.xml b/sandbox-provider-api/pom.xml
index f71ad633..ab9d1162 100644
--- a/sandbox-provider-api/pom.xml
+++ b/sandbox-provider-api/pom.xml
@@ -6,7 +6,7 @@
sandbox
com.alibaba.jvm.sandbox
- 1.1.0
+ 1.1.1-SNAPSHOT
sandbox-provider-api
sandbox-provider-api ${sandbox.version}
diff --git a/sandbox-qatest/pom.xml b/sandbox-qatest/pom.xml
index 02ed5073..8501d40d 100644
--- a/sandbox-qatest/pom.xml
+++ b/sandbox-qatest/pom.xml
@@ -6,7 +6,7 @@
com.alibaba.jvm.sandbox
sandbox
- 1.1.0
+ 1.1.1-SNAPSHOT
com.alibaba.jvm.sandbox
sandbox-qatest
@@ -22,6 +22,18 @@
-Xbootclasspath/p:./lib/sandbox-spy-1.1.0-for-qatest.jar
+
+ org.codehaus.mojo
+ cobertura-maven-plugin
+ 2.7
+
+
+ html
+ xml
+
+
+
+
diff --git a/sandbox-qatest/src/test/java/com/alibaba/jvm/sandbox/qatest/core/enhance/CoreEnhanceBaseTestCase.java b/sandbox-qatest/src/test/java/com/alibaba/jvm/sandbox/qatest/core/enhance/CoreEnhanceBaseTestCase.java
index 824e1927..382a3f34 100644
--- a/sandbox-qatest/src/test/java/com/alibaba/jvm/sandbox/qatest/core/enhance/CoreEnhanceBaseTestCase.java
+++ b/sandbox-qatest/src/test/java/com/alibaba/jvm/sandbox/qatest/core/enhance/CoreEnhanceBaseTestCase.java
@@ -10,7 +10,6 @@
import com.alibaba.jvm.sandbox.core.util.SandboxReflectUtils;
import com.alibaba.jvm.sandbox.core.util.matcher.ExtFilterMatcher;
import com.alibaba.jvm.sandbox.core.util.matcher.structure.ClassStructureImplByJDK;
-import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.ByteArrayInputStream;
@@ -21,54 +20,35 @@
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
-import static com.alibaba.jvm.sandbox.core.util.SandboxStringUtils.toInternalClassName;
+import static com.alibaba.jvm.sandbox.qatest.util.QaClassUtils.toByteArray;
+import static com.alibaba.jvm.sandbox.qatest.util.QaClassUtils.toResourceName;
public class CoreEnhanceBaseTestCase {
private static final AtomicInteger LISTENER_ID_SEQ = new AtomicInteger(1000);
- /**
- * 目标Class文件转换为字节码数组
- *
- * @param targetClass 目标Class文件
- * @return 目标Class文件字节码数组
- * @throws IOException 转换出错
- */
- protected byte[] toByteArray(final Class> targetClass) throws IOException {
- final InputStream is = targetClass.getClassLoader().getResourceAsStream(toResourceName(targetClass.getName()));
- try {
- return IOUtils.toByteArray(is);
- } finally {
- IOUtils.closeQuietly(is);
- }
- }
-
- private String toResourceName(String javaClassName) {
- return toInternalClassName(javaClassName).concat(".class");
- }
-
private class TestClassLoader extends ClassLoader {
private final Map javaClassByteArrayMap
= new HashMap();
-// @Override
-// protected Class> loadClass(String name, boolean resolve) throws ClassNotFoundException {
-// final Class> loadedClass = findLoadedClass(name);
-// if (loadedClass == null) {
-// try {
-// final Class> aClass = findClass(name);
-// if (resolve) {
-// resolveClass(aClass);
-// }
-// return aClass;
-// } catch (Exception e) {
-// return super.loadClass(name, resolve);
-// }
-// } else {
-// return loadedClass;
-// }
-// }
+ @Override
+ protected Class> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ final Class> loadedClass = findLoadedClass(name);
+ if (loadedClass == null) {
+ try {
+ final Class> aClass = findClass(name);
+ if (resolve) {
+ resolveClass(aClass);
+ }
+ return aClass;
+ } catch (Exception e) {
+ return super.loadClass(name, resolve);
+ }
+ } else {
+ return loadedClass;
+ }
+ }
public Class> defineClass(final String javaClassName,
final byte[] classByteArray) throws InvocationTargetException, IllegalAccessException {
diff --git a/sandbox-qatest/src/test/java/com/alibaba/jvm/sandbox/qatest/core/util/matcher/ClassStructureTestCaseByChildClass.java b/sandbox-qatest/src/test/java/com/alibaba/jvm/sandbox/qatest/core/util/matcher/ClassStructureTestCaseByChildClass.java
new file mode 100644
index 00000000..c58425ba
--- /dev/null
+++ b/sandbox-qatest/src/test/java/com/alibaba/jvm/sandbox/qatest/core/util/matcher/ClassStructureTestCaseByChildClass.java
@@ -0,0 +1,361 @@
+package com.alibaba.jvm.sandbox.qatest.core.util.matcher;
+
+import com.alibaba.jvm.sandbox.core.util.matcher.structure.ClassStructure;
+import com.alibaba.jvm.sandbox.core.util.matcher.structure.ClassStructureFactory;
+import com.alibaba.jvm.sandbox.qatest.core.util.matcher.asserts.BehaviorStructureAsserter;
+import com.alibaba.jvm.sandbox.qatest.core.util.matcher.asserts.BehaviorStructureCollectionAsserter;
+import com.alibaba.jvm.sandbox.qatest.core.util.matcher.asserts.ClassStructureAsserter;
+import com.alibaba.jvm.sandbox.qatest.core.util.matcher.target.ChildClass;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import static com.alibaba.jvm.sandbox.qatest.core.util.matcher.asserts.AccessAsserter.AccessIsEnum.*;
+import static com.alibaba.jvm.sandbox.qatest.core.util.matcher.asserts.BehaviorStructureCollectionAsserter.buildBehaviorSignCodeArrayAsserter;
+import static com.alibaba.jvm.sandbox.qatest.core.util.matcher.asserts.ClassStructureCollectionAsserter.buildEmptyJavaClassNameArrayAsserter;
+import static com.alibaba.jvm.sandbox.qatest.core.util.matcher.asserts.ClassStructureCollectionAsserter.buildJavaClassNameArrayAsserter;
+import static com.alibaba.jvm.sandbox.qatest.core.util.matcher.asserts.MappingAsserter.Mode.ALL;
+import static com.alibaba.jvm.sandbox.qatest.util.QaClassUtils.toByteArray;
+import static java.util.Arrays.asList;
+
+@RunWith(Parameterized.class)
+public class ClassStructureTestCaseByChildClass {
+
+ private static final String PACKAGE_PREFIX = "com.alibaba.jvm.sandbox.qatest.core.util.matcher.target.";
+
+ @Parameterized.Parameters
+ public static Collection
+ *
+ * @param clazz
+ * @return
+ */
+ public static Set> getJdkFamilyClassType(Class> clazz) {
+
+ // 获取所有的父类
+ final Set> familyTypes = new LinkedHashSet>(getJdkFamilyClassInterface(clazz));
+
+ for (final Class> superClass : getJdkFamilySuperClasses(clazz)) {
+ familyTypes.add(superClass);
+ familyTypes.addAll(getJdkFamilyClassInterface(superClass));
+ }
+
+ // 递归获取所有接口及其父类
+ return familyTypes;
+ }
+
+ public static Set> getJdkAnnotationType(Class> clazz) {
+ final Set> annotationClasses = new LinkedHashSet>();
+ if(ArrayUtils.isNotEmpty(clazz.getAnnotations())) {
+ for (final Annotation annotation : clazz.getAnnotations()) {
+ if (annotation.getClass().isAnnotation()) {
+ annotationClasses.add(annotation.getClass());
+ }
+ for (final Class annotationInterfaceClass : annotation.getClass().getInterfaces()) {
+ if (annotationInterfaceClass.isAnnotation()) {
+ annotationClasses.add(annotationInterfaceClass);
+ }
+ }
+ }
+ }
+ return annotationClasses;
+ }
+
+
+
+}
diff --git a/sandbox-spy/pom.xml b/sandbox-spy/pom.xml
index b5055bb7..e250a452 100755
--- a/sandbox-spy/pom.xml
+++ b/sandbox-spy/pom.xml
@@ -6,7 +6,7 @@
com.alibaba.jvm.sandbox
sandbox
- 1.1.0
+ 1.1.1-SNAPSHOT
sandbox-spy
sandbox-spy ${sandbox.version}
diff --git a/sandbox-spy/src/main/java/java/com/alibaba/jvm/sandbox/spy/Spy.java b/sandbox-spy/src/main/java/java/com/alibaba/jvm/sandbox/spy/Spy.java
index 19370257..5b6de7fe 100755
--- a/sandbox-spy/src/main/java/java/com/alibaba/jvm/sandbox/spy/Spy.java
+++ b/sandbox-spy/src/main/java/java/com/alibaba/jvm/sandbox/spy/Spy.java
@@ -75,6 +75,14 @@ public static void init(final String namespace,
*/
public static void clean(final String namespace) {
namespaceMethodHookMap.remove(namespace);
+
+ // 如果是最后的一个命名空间,则需要重新清理Node中所持有的Thread
+ if (namespaceMethodHookMap.isEmpty()) {
+ for (int index = 0; index < selfCallBarrier.nodeArray.length; index++) {
+ selfCallBarrier.nodeArray[index] = new SelfCallBarrier.Node();
+ }
+ }
+
}
private static final SelfCallBarrier selfCallBarrier = new SelfCallBarrier();
@@ -226,7 +234,7 @@ void delete(final Node node) {
node.next.pre = node.pre;
}
// help gc
- node.pre = node.next = null;
+ node.pre = (node.next = null);
}
// 插入节点