从字节码解析类名[英] Resolve class name from bytecode

问题描述

是否可以从级别的源代码形成的字节码中挖出类名称?

情况是这样的:我从某个地方远程地远程获得一个课程,它无关紧要.要有效地加载包含ClassLoader的类,我需要拥有类名......对吗?

推荐答案

如果您只需要类名,则可以更轻松地解析类文件的开头,而不是为此目的添加第三方库进行类代码操作.您只需从恒定池中的类和字符串,跳过访问标志,然后替换/用.在课堂名称中.如果您有一个字节数组,则可以使用new ByteArrayInputStream(byteArray):

调用此方法
public static String getClassName(InputStream is) throws Exception {
    DataInputStream dis = new DataInputStream(is);
    dis.readLong(); // skip header and class version
    int cpcnt = (dis.readShort()&0xffff)-1;
    int[] classes = new int[cpcnt];
    String[] strings = new String[cpcnt];
    for(int i=0; i<cpcnt; i++) {
        int t = dis.read();
        if(t==7) classes[i] = dis.readShort()&0xffff;
        else if(t==1) strings[i] = dis.readUTF();
        else if(t==5 || t==6) { dis.readLong(); i++; }
        else if(t==8) dis.readShort();
        else dis.readInt();
    }
    dis.readShort(); // skip access flags
    return strings[classes[(dis.readShort()&0xffff)-1]-1].replace('/', '.');
}

其他推荐答案

最简单的方法可能使用 ASM :

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.commons.EmptyVisitor;

public class PrintClassName {
  public static void main(String[] args) throws IOException {
    class ClassNamePrinter extends EmptyVisitor {
      @Override
      public void visit(int version, int access, String name, String signature,
          String superName, String[] interfaces) {
        System.out.println("Class name: " + name);
      }
    }

    InputStream binary = new FileInputStream(args[0]);
    try {
      ClassReader reader = new ClassReader(binary);
      reader.accept(new ClassNamePrinter(), 0);
    } finally {
      binary.close();
    }
  }
}

如果您不能使用第三方库,则可以读取类文件格式.

其他推荐答案

您应该能够使用javap来拆卸字节代码,如果只是偶尔会发生一次.

在运行时执行它:使用像apache的bcel等字节代码操作库( http://jakarta. apache.org/bcel )分析字节代码.

本文地址:https://www.itbaoku.cn/post/978356.html