代码之家  ›  专栏  ›  技术社区  ›  JHollanti

从字节码解析类名

  •  1
  • JHollanti  · 技术社区  · 16 年前

    是否可以从由类的源代码形成的字节码中挖掘类名称?

    5 回复  |  直到 16 年前
        1
  •  11
  •   Oak    14 年前

    如果您只需要类名,那么自己解析类文件的开头可能会更容易,而不是为此目的添加第三方库来进行类代码操作。您只需要常量池中的类和字符串,跳过访问标志,然后替换为。在类名中。如果您有一个字节数组,可以使用 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('/', '.');
    }
    
        2
  •  2
  •   McDowell rahul gupta    16 年前

    最简单的方法可能是使用 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();
        }
      }
    }
    

    如果您不能使用第三方库,您可以 read the class file format yourself .

        3
  •  1
  •   ankon    16 年前

    javap

    要在运行时执行此操作,请使用字节码操纵库,如Apache的BCEL( http://jakarta.apache.org/bcel )分析字节码。

        4
  •  1
  •   01es    10 年前

    为了完整起见,在可以接受使用ASM5库的情况下,可以使用以下调用从其字节表示中获取类名。

    public String readClassName(final byte[] typeAsByte) {
        return new ClassReader(typeAsByte).getClassName().replace("/", ".");
    }
    
        5
  •  0
  •   user85421    16 年前

    我认为您可以在ClassLoader的子类中使用ClassLoader.defineClass方法来获取给定字节码的类对象。(未测试)