- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我试图用 Javaflow(http://commons.apache.org/sandbox/commons-javaflow/)和 OW2 ASM 库(http://asm.ow2.org/)检测 Java 类。我设置了 javaagent 并使用 Instrumentation.addTransformer() 在加载时将我的转换器注册到仪器类。在转换器内部,我检查是否需要检测某个类。如果是,则执行检测。
症状:总结:在加载和检测某些类后,不会在类加载时调用 transform()。
更多细节:一切都很好。 premain 被正确调用,并且我的转换器在加载的前几个类中被调用。在对特定类(例如 Foo)进行检测后,事情突然变得非常糟糕。我可以看到正在加载的类(通过 -verbose:class 消息),但不会在这些类上调用 transform() 方法。这些类是可修改的。如果我选择不检测 Foo 类,则所有其他类都会正确加载和检测。
可能有助于诊断问题的更多信息:1. 我在想,在检测类 Foo 时,可能在 transform() 内部引发了一些异常。然后我将 transform() 中的代码包含在 try-catch 语句中。但是,没有发现异常。2. 好像不是只有class Foo 可以触发这个问题。其他一些类(我不需要检测但为了测试目的而检测)也可以触发此问题。我找不到可能触发问题的类之间的相似之处。3. 如果在 transform() 内部,我不执行任何检测,所有类加载都由 transform() 正确 Hook 。
有没有人知道是什么导致了这个问题?如有必要,我可以提供有关我正在做的事情的更多信息。
更新:显示症状的最小示例:目录结构如下:
src\
instrumentation\
Instrumentor.java
test\
InstrumentationTest.java
TestRunnable.java
lib\
asm-4.0.jar
asm-commons-4.0.jar
asm-util-4.0.jar
commons-logging-1.1.3.jar
asm-analysis-4.0.jar
asm-tree-4.0.jar
commons-javaflow-2.0-SNAPSHOT.jar
这是 Instrumentor.java 的内容:
package instrumentation;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import org.apache.commons.javaflow.bytecode.transformation.ResourceTransformer;
import org.apache.commons.javaflow.bytecode.transformation.asm.AsmClassTransformer;
public class Instrumentor implements ClassFileTransformer {
public static void premain(String agentArguments,
Instrumentation instrumentation) {
try {
System.out.println("Executing premain");
instrumentation.addTransformer(new Instrumentor());
} catch (Exception e) {
System.out.println("Exception.");
e.printStackTrace();
}
}
static String[] toInstrument = new String[] { "test/InstrumentationTest", "test/TestRunnable" };
// static String[] toInstrument = new String[] { "test/TestRunnable" };
@Override
public byte[] transform(ClassLoader loader, String className,
Class redefiningClass, ProtectionDomain domain, byte[] bytes)
throws IllegalClassFormatException {
try {
ResourceTransformer continuationTransformer = new AsmClassTransformer();
if (className.equals("test/TestRunnable") || className.equals("test/InstrumentationTest")) {
System.out.println(className + " intercepted.");
}
for (String ti : toInstrument) {
if (className.equals(ti)) {
System.out.println("Instrumenting " + className);
byte[] continuationClass = continuationTransformer.transform(bytes);
return continuationClass;
}
}
} catch (Exception e) {
e.printStackTrace();
}
// System.out.println("Not instrumented. " + className);
return bytes;
}
}
然后是InstrumentationTest.java的内容:
package test;
public class InstrumentationTest {
public static void main(String args[]) {
Runnable r = new TestRunnable();
r.run();
}
}
最后是 TestRunnable.java 的内容:
package test;
public class TestRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++)
System.out.println(i);
}
}
示例构建文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project name="project" default="package" basedir=".">
<fileset id="lib" dir="lib" includes="**/*.jar"/>
<pathconvert property="libs" refid="lib" pathsep=":" />
<target name="compile" description="compile class files.">
<mkdir dir="build/classes" />
<javac srcdir="src" destdir="build/classes" debug="true" debuglevel="lines,vars,source">
<classpath>
<fileset dir="lib" includes="**/*.jar" />
</classpath>
</javac>
</target>
<target name="package" description="build the jar file from the compiled classes." depends="compile">
<mkdir dir="build" />
<jar jarfile="build/agent.jar" basedir="build/classes">
<manifest>
<attribute name="Premain-Class" value="instrumentation.Instrumentor" />
</manifest>
</jar>
</target>
<target name="run" description="run the test" depends="package" >
<java fork="true" classname="test.InstrumentationTest">
<classpath>
<fileset dir="lib" includes="**/*.jar" />
<pathelement path="./build/classes" />
</classpath>
<jvmarg value="-Xbootclasspath/p:${libs}" />
<jvmarg value="-javaagent:./build/agent.jar" />
</java>
</target>
<target name="clean">
<delete dir="build" />
</target>
</project>
然后,如果您运行“ant run”,您会发现只有 InstrumentationTest 被检测,但 TestRunnable 没有(它的负载甚至没有被 transform() 拦截)。您可以切换对 toInstrument 数组的评论,以查看如果未检测 InstrumentationTest,transform() 会正确拦截所有类的负载并检测 TestRunnable。
最佳答案
您是否注意到在“Instrumentation.addTransformer”方法的 javadoc 中,它说:“转换器将看到所有 future 的类定义,除了基于的类的定义任何已注册的变压器都是从属的。'
您的情况是否属于这种情况?
关于java - 加载某些类时不会调用 ClassFileTransformer.transform(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22496004/
我使用 ASM 为 javaagent 实现了一个 ClassFileTransformer。因为它有一些bug,我想为它写一个JUnit测试用例。我该怎么做? 使用我认为的伪代码: // Have
我试图用 Javaflow(http://commons.apache.org/sandbox/commons-javaflow/)和 OW2 ASM 库(http://asm.ow2.org/)检测
实时java.lang.instrument.ClassFileTransformer的目的是什么。这仅在分析过程中使用吗? 最佳答案 javadoc API中说那: An agent provide
不同的来源提供了使用 Javassist 实现 ClassFileTransformer 的不同方法: blog.newrelic.com/2014/09/29/diving-bytecode-man
我用 premain 方法编写了一个类,在该方法中我添加了一个 ClassFileTransformer 到 Instrumentation (Instrumentation.addTransform
方法 ClassFileTransformer.transform(ClassLoader classLoader, String className, Class classBeingRedefin
我正在使用 Spring 和 AspectJ 做一些不错的编织,我在插入 后遇到了这个问题。进入我的应用程序上下文: Caused by: java.lang.IllegalStateExcepti
当我尝试将 weblogic.xml 中启用 fast-swap 模式的分解目录部署到 weblogic 10.3 时,出现以下异常 如果我删除
我是一名优秀的程序员,十分优秀!