我正在使用ASM(字节码修改库),它以字节码命名格式提供对类型名称的访问,例如,报告String字段具有描述:Ljava/lang/String
我需要为某些类调用Class.forName,但是我需要类型名称的源代码形式,例如java.lang.String.
有没有办法从内部名称转换为Java源格式?
我正在寻找可用于Dalvik字节码的CGLIB模拟.Android世界中有这样的库吗?
也许,有一种方法可以在运行中将CGLIB结果转换为Davlik字节码?
我正在使用一个称为ASM的字节码库来改变类文件,然后我想将每个类文件写回一个jar文件而不是一个充满类文件的文件夹.我这样做是通过运行此代码:
当ZipException因为不是预期的大小而抛出时,我的问题就出现了
java.util.zip.ZipException: invalid entry compressed size (expected 695 but got 693 bytes)
at java.util.zip.ZipOutputStream.closeEntry(Unknown Source)
at org.steinburg.client.accessor.Accessor.accessJar(Accessor.java:64)
at org.steinburg.client.accessor.Accessor.<init>(Accessor.java:41)
at Loader.main(Loader.java:5)
package org.steinburg.client.accessor;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
public class Accessor {
private String input;
private File inFile;
private JarEntry jarEntry;
private JarFile jarFile;
private Enumeration<JarEntry> entries;
private InputStream is;
private String out;
private File outFile;
private FileOutputStream fos;
private JarOutputStream jos;
private byte[] …Run Code Online (Sandbox Code Playgroud) 我正在从一个JAR文件中读取一堆类,我计划在Java中注入一个简单的方法(然后转储新的jar),它将一些数据发布到PHP文件:
public static void post(final String n, final String o){
try{
final URL url = new URL("http://urltophpfile.com/phpfile.php");
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setReadTimeout(60000);
connection.setConnectTimeout(60000);
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.addRequestProperty("User-Agent", "useragent");
final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
writer.write(String.format("n=%s&p=%s", n, o));
writer.flush();
writer.close();
connection.getInputStream().read();
}catch(IOException ex){
ex.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
然后我使用Intellij Bytecode Viewer查看了它的字节码,它生成:
public static post(Ljava/lang/String;Ljava/lang/String;)V
TRYCATCHBLOCK L0 L1 L2 java/io/IOException
L0
LINENUMBER 11 L0
NEW java/net/URL
DUP
LDC "http://urltophpfile.com/phpfile.phpp"
INVOKESPECIAL java/net/URL.<init> (Ljava/lang/String;)V
ASTORE 2
L3
LINENUMBER 12 L3
ALOAD 2
INVOKEVIRTUAL …Run Code Online (Sandbox Code Playgroud) 我正在尝试生成字节码,它将创建没有代码初始化逻辑的对象实例.其实我想重现generateSerializationConstructor行为.
{
mv = cw.visitMethod(ACC_PUBLIC, "newObjectInstance", "()Ljava/lang/Object;", null, null);
mv.visitCode();
mv.visitTypeInsn(NEW, classNameInternal);
mv.visitInsn(DUP);
classNameInternal = "java/lang/Object";
mv.visitMethodInsn(INVOKESPECIAL, classNameInternal, "<init>", "()V");
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
Run Code Online (Sandbox Code Playgroud)
不幸的是我得到了这样的错误:
java.lang.VerifyError :(类:com/esotericsoftware/reflectasm/benchmark/ConstructorAccessBenchmark $ SomeClass_ ClassAccess _,方法:newObjectInstance签名:()Ljava/lang/Object;)调用错误的初始化方法
我正在实现一个转换,从.class文件中删除未使用的元素以减小它们的大小.因为一些常量池条目将被使用,我让ASM重新计算常量池,而不是从输入中复制它.但是,转换后的.class文件有时比原始文件大,因为ASM的常量池排序需要使用ldc_w输入.class文件ldc(带有1字节索引)的指令(带有2 字节索引).我想手动对常量池进行排序,以便ldc首先引用常量.
有人可能也想要出于其他原因对常量池进行排序:例如,通过将其常量池按规范顺序排列,使一组.class文件更易于压缩,以测试使用.class文件的工具,将订单用作软件水印,或混淆不良实施的反编译器/反混淆器.
我在ASM指南中搜索了"常量",但除了常量池的常规解释之外没有任何有用的命中,并且"希望ASM隐藏与常量池相关的所有细节,因此您不必为此烦恼",在这种情况下,这是有帮助的.
如何控制ASM发出常量池条目的顺序?
使用像javaassist这样的API执行字节码操作,在编译后修改类文件.但是,如果优化了java代码,那么修改是否可以在错误的地方执行?有办法避免这个问题吗?常规Java和Android之间的故事有何不同?
java android bytecode-manipulation javassist java-bytecode-asm
当访问方法指令a.doAnother(account.getId);使用visitMethodInsn()时ASM.我需要从方法参数获取帐户account.getId()类型,帐户类型是Account.但是我得到的返回类型account.getId()是long.如何获得Account此处的帐户类型?
我正在编写一个用于赋值的静态分析工具,它使用ASM库分析Java字节码.我们使用的ASM的一个部分需要(或者至少似乎要求)从ClassLoader加载该类.
我们希望该工具能够分析.class文件,而不需要它们在类路径上.我们已经在运行时从指定目录加载.classes并使用InputStream读取它们.在大多数情况下,这对于ASM是可接受的.有些类,例如SimpleVerifier,尝试加载类.
在这种情况下,是否可以注册要加载的.class文件,以便调用Class.forName()将加载它们?或者是否有一种简单的方法来扩展ClassLoader以允许它?
编辑:URLClassLoader有用的信息.不幸的是,使用Thread.currentThread().setContextClassLoader()它的实例在这种情况下不起作用.我正在调用的库代码使用它在实例初始化时检索的加载器getClass().getClassLoader().
当我设置URLClassLoader时,该类尚未初始化,所以我猜contextClassLoader不加载该类.
我是否正确理解了答案?是否可以使用URLClassLoader加载第三方类?
defineClass(className, byte[], offset, length)。new CustomClassLoader(Thread.currentThread().getContextClassLoader())。因此,CustomClassLoader的父级是当前线程中的ClassLoader。Thread.currentThread().setContextClassLoader()用CustomClassLoader 设置了。Class.forName(String, true, the CustomClassLoader)。我怎么了?如果您需要更多信息,请在我的GitHub上找到详细的主题。
java ×10
bytecode ×4
android ×2
classloader ×2
cglib ×1
classpath ×1
exception ×1
jar ×1
javassist ×1
jvm ×1
reflection ×1
superclass ×1