Is it possible to dig up a classes name from bytecode which is formed from the class\' source code?
The situation is this: I get a classes bytecode remotely from so
Just for completeness, in cases where the use of ASM5 library is acceptable, the following call could be used to obtain the class name from its byte representation.
public String readClassName(final byte[] typeAsByte) {
return new ClassReader(typeAsByte).getClassName().replace("/", ".");
}
If you just need the class name, it's probably easier to parse the beginning of the class file yourself instead of adding a 3rd party library for class code manipulation just for this purpose. You just need the classes and strings from the constant pool, skip the access flags and then replace / with . in the class name. If you have a byte array, you can call this method with 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('/', '.');
}
You should be able to use javap
to disassemble the byte code, if that just happens once in a while.
For doing it at runtime: use a byte-code manipulation library like Apache's BCEL (http://jakarta.apache.org/bcel) to analyse the byte code.
The easiest way is probably using something like 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();
}
}
}
If you can't use a 3rd party library, you could read the class file format yourself.
I think you can use the ClassLoader.defineClass method, in a subclass of ClassLoader, to get the Class object for a given bytecode. (not tested)