How to read the fully qualified name of a .class file
嘿,我想标题总结了一下,但还是这样。
我需要从其编译的.class文件中提取对象的完全限定名称,有人可以指出正确的方向吗?
谢谢,
亚当。
1 | getClass().getName() |
更新:您可以将类文件加载到
1 2 3 4 5 6 7 8 9 | public String getFullClassName(String classFileName) throws IOException { File file = new File(classFileName); FileChannel roChannel = new RandomAccessFile(file,"r").getChannel(); ByteBuffer bb = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, (int)roChannel.size()); Class< ? > clazz = defineClass((String)null, bb, (ProtectionDomain)null); return clazz.getName(); } |
使用诸如BCEL之类的库将类文件读入内存并查询类名称。
您可以通过解析二进制文件来阅读。类文件格式在VM Spec中定义。
如果您不了解二进制文件,请看一下DataInputStream。
您可以看一下JSF Implementation中的AnnotationScanner,它们确实手动加载类(以避免烫发空间污染)以查找JSF注释。特别要看一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | /** * This class is encapsulating binary .class file information as defined at * http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html * <p/> * This is used by the annotation frameworks to quickly scan .class files * for the presence of annotations. This avoid the annotation framework * having to load each .class file in the class loader. * <p/> * Taken from the GlassFish V2 source base. */ @SuppressWarnings({"UnusedDeclaration"}) private static final class ClassFile { private static final int magic = 0xCAFEBABE; public static final int ACC_PUBLIC = 0x1; public static final int ACC_PRIVATE = 0x2; public static final int ACC_PROTECTED = 0x4; public static final int ACC_STATIC = 0x8; public static final int ACC_FINAL = 0x10; public static final int ACC_SYNCHRONIZED = 0x20; public static final int ACC_THREADSAFE = 0x40; public static final int ACC_TRANSIENT = 0x80; public static final int ACC_NATIVE = 0x100; public static final int ACC_INTERFACE = 0x200; public static final int ACC_ABSTRACT = 0x400; public short majorVersion; public short minorVersion; public ConstantPoolInfo constantPool[]; public short accessFlags; public ConstantPoolInfo thisClass; public ConstantPoolInfo superClass; public ConstantPoolInfo interfaces[]; /** * bunch of stuff I really don't care too much for now. * <p/> * FieldInfo fields[]; MethodInfo methods[]; * AttributeInfo attributes[]; */ ByteBuffer header; ConstantPoolInfo constantPoolInfo = new ConstantPoolInfo(); // ------------------------------------------------------------ Constructors /** * Creates a new instance of ClassFile */ public ClassFile() { header = ByteBuffer.allocate(12000); } // ---------------------------------------------------------- Public Methods public void setConstantPoolInfo(ConstantPoolInfo poolInfo) { constantPoolInfo = poolInfo; } /** * Read the input channel and initialize instance data structure. * * @param in a <wyn>ReadableByteChannel</wyn> that provides the bytes * of the classfile * * @return <wyn>true</wyn> if the bytes representing this classfile include * one of the annotations we're looking for. * * @throws IOException if an I/O error occurs while reading the class */ public boolean containsAnnotation(ReadableByteChannel in) throws IOException { /** * this is the .class file layout * ClassFile { u4 magic; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count]; u2 fields_count; field_info fields[fields_count]; u2 methods_count; method_info methods[methods_count]; u2 attributes_count; attribute_info attributes[attributes_count]; } **/ header.clear(); long read = (long) in.read(header); if (read == -1) { return false; } header.rewind(); if (header.getInt() != magic) { return false; } minorVersion = header.getShort(); majorVersion = header.getShort(); int constantPoolSize = header.getShort(); return constantPoolInfo .containsAnnotation(constantPoolSize, header, in); } } // END ClassFile |
根据您使用的IDE,可能会有执行此操作的机制。例如,在eclipse中,您可以向下钻取.class文件并右键单击它,然后选择"复制完全限定名称"。
较早版本的eclipse可能没有此功能,但是我之前使用过此插件:
http://www.jave.de/eclipse/copyfully/index.html
它的工作方式几乎相同。希望这可以帮助。