我在罐子里有一个类的方法,我想用自己的身体交换它.在这种情况下,我只想让方法将"GOT IT"打印到控制台并返回true;
我正在使用系统加载器来加载jar的类.我使用反射使系统类加载器能够通过字节码加载类.这部分似乎工作正常.
我按照这里找到的方法替换示例:asm.ow2.org/current/asm-transformations.pdf.
我的代码如下:
public class Main
{
public static void main(String[] args)
{
URL[] url = new URL[1];
try
{
url[0] = new URL("file:////C://Users//emist//workspace//tmloader//bin//runtime//tmgames.jar");
verifyValidPath(url[0]);
}
catch (Exception ex)
{
System.out.println("URL error");
}
Loader l = new Loader();
l.loadobjection(url);
}
public static void verifyValidPath(URL url) throws FileNotFoundException
{
File filePath = new File(url.getFile());
if (!filePath.exists())
{
throw new FileNotFoundException(filePath.getPath());
}
}
}
class Loader
{
private static final Class[] parameters = new Class[] {URL.class};
public static void addURL(URL …Run Code Online (Sandbox Code Playgroud) 我试图获取Java程序的方法参数的值.我正在使用ASM来检测字节码并获取这些值.但是,我遇到了一些麻烦.
这是用于检测代码的visitCode()方法.它正在做的是:
.
@Override
public void visitCode() {
int paramLength = paramTypes.length;
// Create array with length equal to number of parameters
mv.visitIntInsn(Opcodes.BIPUSH, paramLength);
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
mv.visitVarInsn(Opcodes.ASTORE, paramLength);
// Fill the created array with method parameters
int i = 0;
for (Type tp : paramTypes) {
mv.visitVarInsn(Opcodes.ALOAD, paramLength);
mv.visitIntInsn(Opcodes.BIPUSH, i);
if (tp.equals(Type.BOOLEAN_TYPE) || tp.equals(Type.BYTE_TYPE) || tp.equals(Type.CHAR_TYPE) || tp.equals(Type.SHORT_TYPE) || tp.equals(Type.INT_TYPE))
mv.visitVarInsn(Opcodes.ILOAD, i);
else if (tp.equals(Type.LONG_TYPE)) {
mv.visitVarInsn(Opcodes.LLOAD, i);
i++;
}
else if (tp.equals(Type.FLOAT_TYPE))
mv.visitVarInsn(Opcodes.FLOAD, i);
else if …Run Code Online (Sandbox Code Playgroud) 我目前正在尝试通过精心设计的java-asm库(版本4)生成代码.更具体地说,我想在每次返回调用之前将代码附加到方法的末尾.我成功地能够在方法代码之前添加代码.但是目前我不知道如何进行上述转换.我真的很感激指出如何实现这一目标.
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 42);
return mv;
Run Code Online (Sandbox Code Playgroud) 我正在使用ASM Java库来替换一些反射.我生成了这个方法的主体:
void set(Object object, int fieldIndex, Object value);
Run Code Online (Sandbox Code Playgroud)
使用此生成的方法,我可以在运行时在不使用反射的情况下在对象上设置字段.它很棒.但是,我发现原始字段失败了.这是我的set方法的相关部分:
for (int i = 0, n = cachedFields.length; i < n; i++) {
mv.visitLabel(labels[i]);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, targetClassName);
mv.visitVarInsn(ALOAD, 3);
Field field = cachedFields[i].field;
Type fieldType = Type.getType(field.getType());
mv.visitFieldInsn(PUTFIELD, targetClassName, field.getName(), fieldType.getDescriptor());
mv.visitInsn(RETURN);
}
Run Code Online (Sandbox Code Playgroud)
此代码为选择生成案例标签.它适用于对象,但对于原语,我收到此错误:
期待在堆栈上找到浮动
好的,这是有道理的,我需要自己进行拆箱.我实现了以下内容:
for (int i = 0, n = cachedFields.length; i < n; i++) {
mv.visitLabel(labels[i]);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, targetClassName);
mv.visitVarInsn(ALOAD, 3);
Field field = …Run Code Online (Sandbox Code Playgroud) 我正在使用asm库来执行一些Java字节码修改 - 专门用于修改我的类以实现新的接口和相关方法.我目前的方法是通过javaagent使用核心asm API.我想保留这种动态方法,而不是静态修改.class文件.
在更高的层次上,我的问题是,如果我选择修改从B扩展的A类,我还需要修改B.(鉴于我对如何在JVM中加载类的理解,我相信B类将永远是在A级之前交给变压器.(如果我错了,请纠正我.)鉴于这个假设,我认为我需要返回并重新转换 B.我的方法在这段代码中被捕获:
public byte[] transform(ClassLoader l, String name, Class<?> clazz, ProtectionDomain d, byte[] b) {
throws IllegalClassFormatException {
// **1**
System.out.println("--->>> " + name);
if (interestingClass(name)) {
try {
ClassReader cr = new ClassReader(b);
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
PyClassVisitorAdapter pv = new PyClassVisitorAdapter(cw, name);
cr.accept(pv, 0);
// **2** Retrieve the superclass and try to transform that
if (! "Ljava/lang/Object;".equals(pv.getSuperName())) {
String cName = classJvmToCanonical(pv.getSuperName());
Class[] classes = inst.getAllLoadedClasses();
for (Class c …Run Code Online (Sandbox Code Playgroud) 我试图弄清楚方法的字节码大小,因为我想确保它足够小,以便通过编译器优化来内联.
我看到内联方法的默认最大大小为35,所以如果方法大于该方法,我将修改代码或将其分解为多个方法.
我有一个生成下面的字节码的方法(通过IntelliJ IDEA的ASM字节码大纲插件进行反汇编).
如何判断该方法的字节码大小?LINENUMBER似乎引用了原始源代码的行号.
TIA
public static mergeNativeArrays([Ljava/lang/Object;[Ljava/lang/Object;IZ)[Ljava/lang/Object;
L0
LINENUMBER 865 L0
ALOAD 0
ASTORE 4
L1
LINENUMBER 867 L1
ILOAD 2
IFGE L2
L3
LINENUMBER 868 L3
ALOAD 0
ARRAYLENGTH
ISTORE 2
L2
LINENUMBER 870 L2
FRAME APPEND [[Ljava/lang/Object;]
ILOAD 2
ALOAD 1
ARRAYLENGTH
IADD
ISTORE 5
L4
LINENUMBER 872 L4
ALOAD 4
ARRAYLENGTH
ILOAD 5
IF_ICMPGE L5
L6
LINENUMBER 874 L6
ILOAD 3
IFEQ L7
L8
LINENUMBER 875 L8
ILOAD 5
INVOKESTATIC railo/commons/math/MathUtil.nextPowerOf2 (I)I
ISTORE 5
L7 …Run Code Online (Sandbox Code Playgroud) 我正在使用ASM进行在线字节码方法内联优化.我的更改基于示例3.2.6 Inline Method(http://asm.ow2.org/current/asm-transformations.pdf).测试示例(在Caller :: test中内联被调用者的计算(int,int))是:
public class Caller {
final Callee _callee;
public Caller(Callee callee){
_callee = callee;
}
public static void main(String[] args) {
new Caller(new Callee("xu", "shijie")).test(5, 100);
}
public void test(int a, int b){
int t = a;
int p = b;
int r = t+p-_callee.calculate(a, b);
int m = t-p;
System.out.println(t);
}
}
public class Callee {
final String _a;
final String _b;
public Callee(String a, String b){
_a = a;
_b …Run Code Online (Sandbox Code Playgroud) java bytecode inline bytecode-manipulation java-bytecode-asm
编译java文件时在IntelliJ项目上出现此错误.没有列出特定的源文件,但它失败并出现此错误.
删除以下编译器标志可修复错误:
-source 1.5 -target 1.5
Run Code Online (Sandbox Code Playgroud)
但是,由于我们的目标是Java 5,因此需要将它们放在那里.是否存在try/catch导致此错误的特定代码(可能是块)?
2013-10-15 16:21:50,556 [26947209] INFO - ompiler.BackendCompilerWrapper - JSR/RET are not supported with computeFrames option
java.lang.RuntimeException: JSR/RET are not supported with computeFrames option
at org.objectweb.asm.Frame.a(Unknown Source)
at org.objectweb.asm.MethodWriter.visitJumpInsn(Unknown Source)
at org.objectweb.asm.MethodAdapter.visitJumpInsn(Unknown Source)
at org.objectweb.asm.ClassReader.accept(Unknown Source)
at org.objectweb.asm.ClassReader.accept(Unknown Source)
at com.intellij.compiler.impl.javaCompiler.BackendCompilerWrapper$ClassParsingThread.a(BackendCompilerWrapper.java:893)
at com.intellij.compiler.impl.javaCompiler.BackendCompilerWrapper$ClassParsingThread.run(BackendCompilerWrapper.java:846)
at com.intellij.openapi.application.impl.ApplicationImpl$7.run(ApplicationImpl.java:386)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:680)
at com.intellij.openapi.application.impl.ApplicationImpl$1$1.run(ApplicationImpl.java:130)
Run Code Online (Sandbox Code Playgroud) 我是ASM框架的新手.我已经在这个ASM框架上工作了一个星期.我在网上看过关于解析类和从头开始生成.class文件的教程.但我无法遵循如何修改ASM中的现有类.
请帮助我.
我无法遵循ClassVisitor,ClassWriter和ClassReader之间的执行流程.
请通过为我提供以下代码的ASM示例来解决我的问题.
public class ClassName {
public void showOne()
{
System.out.println("Show One Method");
}
public static void main(String[] args) {
ClassName c=new ClassName();
c.showOne();
}
}
Run Code Online (Sandbox Code Playgroud)
上述类应修改为:
public class ClassName {
public void showOne()
{
System.out.println("Show One Method");
}
public void showTwo()
{
System.out.println("Show Two Method");
}
public static void main(String[] args) {
ClassName c=new ClassName();
c.showOne();
c.showTwo();
}
}
Run Code Online (Sandbox Code Playgroud)
什么应该是ASM代码来修改它?
我使用ASMifier工具生成代码.但我不知道在哪里应用它.
请帮我.+