- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 Java 工具和 Javassist将 print 语句插入方法中。这大多数情况下都不会出现错误,但对于某些类方法(例如 java.util.TimeZone.getSystemTimeZoneID),我收到以下异常:
javassist.CannotCompileException: no method body
at javassist.CtBehavior.insertBefore(CtBehavior.java:695)
at javassist.CtBehavior.insertBefore(CtBehavior.java:685)
我的代码尝试通过检查CtBehaviour.isEmpty()
来避免此问题,但这没有什么区别。关于如何避免这种情况有什么建议吗?
这是一个最小的例子:
public class ExceptionExample implements ClassFileTransformer {
private static final ClassPool pool = ClassPool.getDefault();
public static void premain(String agentArgument,
Instrumentation instrumentation) {
instrumentation.addTransformer(new ExceptionExample());
}
@Override
public byte[] transform(final ClassLoader loader, final String className,
final Class<?> classBeingRedefined,
final ProtectionDomain protectionDomain, final byte[] classfileBuffer)
throws IllegalClassFormatException {
String dottedClassName = className.replace('/', '.');
if (dottedClassName.startsWith("java.lang")
|| dottedClassName.startsWith("java.util")) {
try {
System.out.println("Instrumenting: " + dottedClassName);
return adjustClass(dottedClassName, classBeingRedefined,
classfileBuffer);
} catch (Exception e) {
e.printStackTrace();
}
}
return classfileBuffer;
}
private byte[] adjustClass(final String className,
final Class<?> classBeingRedefined, final byte[] classfileBuffer)
throws IOException, RuntimeException, CannotCompileException {
CtClass cl = null;
try {
cl = pool.makeClass(new java.io.ByteArrayInputStream(classfileBuffer));
if (!cl.isInterface()) {
CtBehavior[] methods = cl.getDeclaredBehaviors();
for (CtBehavior method : methods) {
if (!method.isEmpty()) {
try {
method
.insertBefore(String.format(
"System.out.println(\"CALLING: %s\");",
method.getLongName()));
} catch (Throwable t) {
System.out.println("Error instrumenting " + className + "."
+ method.getName());
t.printStackTrace();
}
}
}
return cl.toBytecode();
}
} finally {
if (cl != null) {
cl.detach();
}
}
return classfileBuffer;
}
}
这是我正在测试的一个小类:
public class Main {
public static void main(String[] args) throws Exception {
Calendar c = Calendar.getInstance();
System.out.println(c.get(Calendar.YEAR));
}
}
示例输出(缩写):
Instrumenting: java.util.Calendar
CALLING: java.util.Calendar.<clinit>()
CALLING: java.util.Calendar.getInstance()
Instrumenting: java.util.TimeZone
Error instrumenting java.util.TimeZone.getSystemTimeZoneID
javassist.CannotCompileException: no method body
at javassist.CtBehavior.insertBefore(CtBehavior.java:695)
at javassist.CtBehavior.insertBefore(CtBehavior.java:685)
at com.cryptomathic.test.instrument.ExceptionExample.adjustClass(ExceptionExample.java:56)
at com.cryptomathic.test.instrument.ExceptionExample.transform(ExceptionExample.java:34)
at sun.instrument.TransformerManager.transform(Unknown Source)
at sun.instrument.InstrumentationImpl.transform(Unknown Source)
at java.util.Calendar.getInstance(Unknown Source)
at test.Main.main(Main.java:8)
Error instrumenting java.util.TimeZone.getSystemGMTOffsetID
javassist.CannotCompileException: no method body
at javassist.CtBehavior.insertBefore(CtBehavior.java:695)
at javassist.CtBehavior.insertBefore(CtBehavior.java:685)
at com.cryptomathic.test.instrument.ExceptionExample.adjustClass(ExceptionExample.java:56)
at com.cryptomathic.test.instrument.ExceptionExample.transform(ExceptionExample.java:34)
at sun.instrument.TransformerManager.transform(Unknown Source)
at sun.instrument.InstrumentationImpl.transform(Unknown Source)
at java.util.Calendar.getInstance(Unknown Source)
at test.Main.main(Main.java:8)
CALLING: java.util.TimeZone.<clinit>()
CALLING: java.util.TimeZone.getDefaultRef()
CALLING: java.util.TimeZone.getDefaultInAppContext()
CALLING: java.util.TimeZone.setDefaultZone()
CALLING: java.util.TimeZone.getTimeZone(java.lang.String,boolean)
CALLING: java.util.TimeZone.setID(java.lang.String)
...
最佳答案
您需要首先检查它是否是 native 方法,因为 native 方法不支持这些方法(insertBefore()、insertAfter()..)。我写了一个小方法来检测 CtMethod 是否是原生的:
public static boolean isNative(CtMethod method) {
return Modifier.isNative(method.getModifiers());
}
我已经测试过它,它有效并解决了您的问题。
注意:无法检测 native 方法,因为它们没有字节码。但是,如果支持 native 方法前缀 ( Transformer.isNativeMethodPrefixSupported() ),那么您可以使用 Transformer.setNativeMethodPrefix() 将 native 方法调用包装在非 native 调用中,然后可以对其进行检测。
关于java - 如何避免 'javassist.CannotCompileException: no method body',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22992546/
我正在尝试通过javassist调用java.util.Arrays.asList(..)。但是得到下面的异常。 javassist.CannotCompileException: [source e
嗯尝试检测一种方法来完成以下任务。 任务 - 创建映射并将值插入到映射中添加 System.out.println 行不会导致任何异常。但是,当我添加行来创建 map 时,由于缺少;,它会抛出cann
我现在正在尝试在我的网络应用程序中编写一些字节码操作,当我尝试将代码注入(inject)到我的方法中时,它总是会抛出错误 javassist.CannotCompileException: [sour
我正在尝试使用 javassist 来将 System.out.println 添加到现有类的方法中,使用此代码 - .... ClassPool pool = new ClassPool();
我正在使用 Java 工具和 Javassist将 print 语句插入方法中。这大多数情况下都不会出现错误,但对于某些类方法(例如 java.util.TimeZone.getSystemTimeZ
我正在尝试使用字节码检测添加 try catch block 。 基本上,我有一个“Lion”类。我想在 try block 中捕获其方法“stayLion()”之一的全部内容并给出相应的 catch
引用:http://jboss-javassist.github.io/javassist/tutorial/tutorial2.html method.insertBefore("{ System.
我正在执行以下操作并获得奖励: Exception in thread "main" java.lang.NoClassDefFoundError: javassist/CannotCompi
我正在使用 javassist 来更改方法体。当该方法在应用程序中定义时我可以做到这一点。但是,当我想更改应用程序使用的 jar 文件中定义的方法时,我会收到以下运行时错误: javassist.Ca
我是一名优秀的程序员,十分优秀!