Skip to content

Commit

Permalink
修复问题 alibaba#133
Browse files Browse the repository at this point in the history
  • Loading branch information
dongchenxu committed Feb 1, 2019
1 parent 03ebfc6 commit 8b07856
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.alibaba.jvm.sandbox.api.listener.ext.AdviceListener;
import com.alibaba.jvm.sandbox.api.listener.ext.EventWatchBuilder;
import com.alibaba.jvm.sandbox.qatest.api.mock.MockForBuilderModuleEventWatcher;
import com.alibaba.jvm.sandbox.qatest.api.mock.MockForBuilderProgress;
import com.alibaba.jvm.sandbox.qatest.api.util.ApiQaArrayUtils;
import org.junit.Assert;
import org.junit.Test;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,27 @@

import com.alibaba.jvm.sandbox.api.event.Event;
import com.alibaba.jvm.sandbox.core.enhance.weaver.asm.EventWeaver;
import com.alibaba.jvm.sandbox.core.util.AsmUtils;
import com.alibaba.jvm.sandbox.core.util.ObjectIDs;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.Set;

import static com.alibaba.jvm.sandbox.core.util.SandboxStringUtils.toInternalClassName;
import static com.alibaba.jvm.sandbox.core.util.SandboxStringUtils.toJavaClassName;
import static org.apache.commons.io.FileUtils.writeByteArrayToFile;
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;

/**
* 事件代码增强器
* Created by luanjia@taobao.com on 16/7/12.
*
* @author luanjia@taobao.com
*/
public class EventEnhancer implements Enhancer {

Expand All @@ -46,57 +49,42 @@ private ClassWriter createClassWriter(final ClassLoader targetClassLoader,
*/
@Override
protected String getCommonSuperClass(String type1, String type2) {
Class<?> c, d;
try {
c = Class.forName(toJavaClassName(type1), false, targetClassLoader);
d = Class.forName(toJavaClassName(type2), false, targetClassLoader);
} catch (Exception e) {
throw new RuntimeException(e);
}
if (c.isAssignableFrom(d)) {
return type1;
}
if (d.isAssignableFrom(c)) {
return type2;
}
if (c.isInterface() || d.isInterface()) {
return "java/lang/Object";
} else {
do {
c = c.getSuperclass();
} while (!c.isAssignableFrom(d));
return toInternalClassName(c.getName());
}
return AsmUtils.getCommonSuperClass(type1, type2, targetClassLoader);
}

};
}

// /*
// * dump class to file
// * 用于代码调试
// */
// private static byte[] dumpClassIfNecessary(String className, byte[] data) {
// final File dumpClassFile = new File("./sandbox-class-dump/" + className + ".class");
// final File classPath = new File(dumpClassFile.getParent());
//
// // 创建类所在的包路径
// if (!classPath.mkdirs()
// && !classPath.exists()) {
// logger.warn("create dump classpath={} failed.", classPath);
// return data;
// }
//
// // 将类字节码写入文件
// try {
// writeByteArrayToFile(dumpClassFile, data);
// logger.info("dump {} to {} success.", className, dumpClassFile);
// } catch (IOException e) {
// logger.warn("dump {} to {} failed.", className, dumpClassFile, e);
// }
//
// return data;
// }
private static final boolean isDumpClass = false;

/*
* dump class to file
* 用于代码调试
*/
private static byte[] dumpClassIfNecessary(String className, byte[] data) {
if (!isDumpClass) {
return data;
}
final File dumpClassFile = new File("./sandbox-class-dump/" + className + ".class");
final File classPath = new File(dumpClassFile.getParent());

// 创建类所在的包路径
if (!classPath.mkdirs()
&& !classPath.exists()) {
logger.warn("create dump classpath={} failed.", classPath);
return data;
}

// 将类字节码写入文件
try {
writeByteArrayToFile(dumpClassFile, data);
logger.info("dump {} to {} success.", className, dumpClassFile);
} catch (IOException e) {
logger.warn("dump {} to {} failed.", className, dumpClassFile, e);
}

return data;
}

@Override
public byte[] toByteCodeArray(final ClassLoader targetClassLoader,
Expand All @@ -119,7 +107,7 @@ public byte[] toByteCodeArray(final ClassLoader targetClassLoader,
),
EXPAND_FRAMES
);
return cw.toByteArray();
return dumpClassIfNecessary(cr.getClassName(), cw.toByteArray());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.alibaba.jvm.sandbox.core.util;

import com.alibaba.jvm.sandbox.core.util.matcher.structure.ClassStructure;
import com.alibaba.jvm.sandbox.core.util.matcher.structure.ClassStructureFactory;
import org.apache.commons.io.IOUtils;

import java.io.InputStream;

import static com.alibaba.jvm.sandbox.core.util.SandboxStringUtils.toInternalClassName;

/**
* ASM工具集
*
* @author luanjia@taobao.com
*/
public class AsmUtils {

/**
* {@see org.objectweb.asm.ClassWriter#getCommonSuperClass(String, String)}
*/
public static String getCommonSuperClass(String type1, String type2, ClassLoader loader) {
return getCommonSuperClassImplByAsm(type1, type2, loader);
}

// implements by ASM
private static String getCommonSuperClassImplByAsm(String type1, String type2, ClassLoader targetClassLoader) {
InputStream inputStreamOfType1 = null, inputStreamOfType2 = null;
try {
inputStreamOfType1 = targetClassLoader.getResourceAsStream(type1 + ".class");
if (null == inputStreamOfType1) {
return "java/lang/Object";
}
inputStreamOfType2 = targetClassLoader.getResourceAsStream(type2 + ".class");
if (null == inputStreamOfType2) {
return "java/lang/Object";
}
final ClassStructure classStructureOfType1 = ClassStructureFactory.createClassStructure(inputStreamOfType1, targetClassLoader);
final ClassStructure classStructureOfType2 = ClassStructureFactory.createClassStructure(inputStreamOfType2, targetClassLoader);
if (classStructureOfType2.getFamilyTypeClassStructures().contains(classStructureOfType1)) {
return type1;
}
if (classStructureOfType1.getFamilyTypeClassStructures().contains(classStructureOfType2)) {
return type2;
}
if (classStructureOfType1.getAccess().isInterface()
|| classStructureOfType2.getAccess().isInterface()) {
return "java/lang/Object";
}
ClassStructure classStructure = classStructureOfType1;
do {
classStructure = classStructure.getSuperClassStructure();
if (null == classStructure) {
return "java/lang/Object";
}
} while (!classStructureOfType2.getFamilyTypeClassStructures().contains(classStructure));
return toInternalClassName(classStructure.getJavaClassName());
} finally {
IOUtils.closeQuietly(inputStreamOfType1);
IOUtils.closeQuietly(inputStreamOfType2);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,13 @@ public MyCalculator(String tCaseName) {
.toUpperCase());
}

public MyCalculator() {
super();
}

@Override
public int sum(int... numArray) {
return super.sum(numArray);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import static com.alibaba.jvm.sandbox.api.event.Event.Type.CALL_BEFORE;
import static com.alibaba.jvm.sandbox.api.event.Event.Type.LINE;
import static com.alibaba.jvm.sandbox.qatest.core.util.CalculatorHelper.*;
import static com.alibaba.jvm.sandbox.qatest.core.util.CalculatorHelper.newInstance;
import static org.junit.Assert.assertEquals;

/**
Expand All @@ -35,8 +34,9 @@ public void onEvent(Event event) throws Throwable {
)
.loadClass(CALCULATOR_CLASS_NAME);

final Object objectOfCal = newInstance(calculatorClass);
for (int i = 0; i < 1000000; i++) {
assertEquals(30, sum(newInstance(calculatorClass), 10, 20));
assertEquals(30, sum(objectOfCal, 10, 20));
}
}

Expand All @@ -58,8 +58,9 @@ public void onEvent(Event event) throws Throwable {
)
.loadClass(CALCULATOR_CLASS_NAME);

final Object objectOfCal = newInstance(calculatorClass);
for (int i = 0; i < 1000000; i++) {
assertEquals(30, sum(newInstance(calculatorClass), 10, 20));
assertEquals(30, sum(objectOfCal, 10, 20));
}
}

Expand All @@ -81,8 +82,9 @@ public void onEvent(Event event) throws Throwable {
)
.loadClass(CALCULATOR_CLASS_NAME);

final Object objectOfCal = newInstance(calculatorClass);
for (int i = 0; i < 1000000; i++) {
assertEquals(30, sum(newInstance(calculatorClass), 10, 20));
assertEquals(30, sum(objectOfCal, 10, 20));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.alibaba.jvm.sandbox.qatest.core.issues;

import org.junit.Assert;
import org.junit.Test;

import java.io.InputStream;

import static com.alibaba.jvm.sandbox.core.util.AsmUtils.getCommonSuperClass;

public class Issues133 {

@Test
public void test() {
final ClassLoader loader = getClass().getClassLoader();
Assert.assertEquals("java/io/InputStream", getCommonSuperClass("java/io/FileInputStream", "javax/servlet/ServletInputStream", loader));
Assert.assertEquals("java/lang/Exception", getCommonSuperClass("java/io/IOException", "javax/servlet/ServletException", loader));
Assert.assertEquals("javax/servlet/ServletResponse", getCommonSuperClass("javax/servlet/ServletResponse", "javax/servlet/http/HttpServletResponse", loader));
Assert.assertEquals("javax/servlet/ServletResponse", getCommonSuperClass("javax/servlet/http/HttpServletResponse", "javax/servlet/ServletResponse", loader));
Assert.assertEquals("java/lang/Object", getCommonSuperClass("java/lang/Throwable", "java/io/FileInputStream", loader));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.alibaba.jvm.sandbox.api.filter.NameRegexFilter;
import com.alibaba.jvm.sandbox.core.util.UnCaughtException;
import com.alibaba.jvm.sandbox.qatest.core.enhance.target.Calculator;
import com.alibaba.jvm.sandbox.qatest.core.enhance.target.MyCalculator;

import java.lang.reflect.InvocationTargetException;
import java.util.Stack;
Expand All @@ -22,6 +23,7 @@
public class CalculatorHelper {

public static final String CALCULATOR_CLASS_NAME = getJavaClassName(Calculator.class);
public static final String MY_CALCULATOR_CLASS_NAME = getJavaClassName(MyCalculator.class);

/**
* 拦截sum()方法过滤器
Expand Down Expand Up @@ -68,6 +70,15 @@ public class CalculatorHelper {
"<init>"
);

/**
* 拦截sum()方法过滤器
*/
public static final Filter MY_CALCULATOR_SUM_FILTER
= new NameRegexFilter(
"^com\\.alibaba\\.jvm.sandbox\\.qatest\\.core\\.enhance\\.target\\.MyCalculator$",
"^sum$"
);

public static final Filter CALCULATOR_INIT_FILTER_WITH_TEST_CASE
= new Filter() {
@Override
Expand Down

0 comments on commit 8b07856

Please sign in to comment.