All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zoodb.jdo.internal.util.ClassDebugger Maven / Gradle / Ivy

The newest version!
package org.zoodb.jdo.internal.util;

import java.nio.ByteBuffer;
import java.util.Arrays;

public class ClassDebugger {

	private static final byte[] BA = {
		-54, -2, -70, -66,  // 0-3: magic number 
		0, 0,  //4-5: minor version 
		0, 50,  //6-7: major version 
		0, 16,  //8-9: constant pools size+1
		7, 0, 2, 1, 0, 11, 98, 99, 101, 47, 
		77, 121, 67, 108, 97, 115, 115, 7, 0, 4, 
		1, 0, 25, 98, 99, 101, 47, 80, 101, 114, 
		115, 105, 115, 116, 101, 110, 116, 67, 97, 112, 
		97, 98, 108, 101, 73, 109, 112, 108, 1, 0, 
		6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 
		40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 
		10, 0, 3, 0, 9, 12, 0, 5, 0, 6, 
		1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 
		98, 101, 114, 84, 97, 98, 108, 101, 1, 0, 
		18, 76, 111, 99, 97, 108, 86, 97, 114, 105, 
		97, 98, 108, 101, 84, 97, 98, 108, 101, 1, 
		0, 4, 116, 104, 105, 115, 1, 0, 13, 76, 
		98, 99, 101, 47, 77, 121, 67, 108, 97, 115, 
		115, 59, 1, 0, 10, 83, 111, 117, 114, 99, 
		101, 70, 105, 108, 101, 1, 0, 12, 77, 121, 
		67, 108, 97, 115, 115, 46, 106, 97, 118, 97, 
		0, 33, 0, 1, 0, 3, 0, 0, 0, 0, 
		0, 1, 0, 1, 0, 5, 0, 6, 0, 1, 
		0, 7, 0, 0, 0, 47, 0, 1, 0, 1, 
		0, 0, 0, 5, 42, -73, 0, 8, -79, 0, 
		0, 0, 2, 0, 10, 0, 0, 0, 6, 0, 
		1, 0, 0, 0, 3, 0, 11, 0, 0, 0, 
		12, 0, 1, 0, 0, 0, 5, 0, 12, 0, 
		13, 0, 0, 0, 1, 0, 14, 0, 0, 0, 
		2, 0, 15
	};

	
	public enum CP {
		CONSTANT_0,
		CONSTANT_Utf8, // 1 Laenge des unterminierten Strings in Anzahl Byte (2 bytes)
		//String in Utf8-Darstellung (variable Laenge)
		CONSTANT_Unicode, // 2 Laenge nachfolgenden Zeichenkette in Anzahl Byte (2 bytes)
		//Unicode-Zeichenkette (variable Laenge)
		CONSTANT_Integer, // 3 Vorzeichenbehafteter Integer-Wert, big-endian (4 bytes)
		CONSTANT_Float, // 4 Float-Wert nach IEEE 754 (4 bytes)
		CONSTANT_Long, // 5 Vorzeichenbehafteter Integer-Wert, big-endian (8 bytes)
		CONSTANT_Double, // 6 Double-Wert nach IEEE 754 (8 bytes)
		CONSTANT_Class, // 7 Index zu einem weiteren Konstantpool-Eintrag vom Typ CONSTANT_Utf8, der
		//den Klassennamen beinhaltet (2 bytes)
		CONSTANT_String, // 8 Index zu einem weiteren Konstantpool-Eintrag vom Typ CONSTANT_Utf8, der
		//den String beinhaltet (2 bytes)
		CONSTANT_Fieldref, // 9 Index zu einem CONSTANT_Class Eintrag, der die Klasse bezeichnet, die das
		//Feld enthaelt (2 bytes) plus ein Index zu einem CONSTANT_NameAndType Eintrag,
		//der die Signatur des Feldes angibt (2 bytes)
		CONSTANT_Methodref, // A Index zu einem CONSTANT_Class Eintrag, der die Klasse bezeichnet, welche die
		//Methode enthaelt (2 bytes) plus ein Index zu einem CONSTANT_NameAndType
		//Eintrag, der die Signatur der Methode angibt (2 bytes)
		CONSTANT_InterfaceMethodref, // B Index zu einem CONSTANT_Class Eintrag, der das Interface bezeichnet, welches
		//die jeweilige Methode deklariert (2 bytes) plus ein Index zu einem
		//CONSTANT_NameAndType Eintrag, der die Signatur des Interfaces angibt (2
		//bytes)
		CONSTANT_NameAndType, // C Index zu einem CONSTANT_Utf8 Eintrag, der den Namen des Feldes oder der
		//Methode enthaelt (2 bytes) plus ein weiteren Index zu einem CONSTANT_Utf8
		//Eintrag, der die Signatur des Feldes oder der Methode angibt (2 bytes)
	}
	
	
	private static final int ACC_PUBLIC = 0x0001;// Kann ausserhalb des Package verwendet werden.
	private static final int ACC_PRIVATE = 0x0002; // Kann nur von innerhalb der Klasse zugegriffen werden.
	private static final int ACC_PROTECTED = 0x0004; // Kann von innerhalb der Klasse und von abgeleiteten Klassen
										// zugegriffen werden.
	private static final int ACC_STATIC = 0x0008; // Als static deklariert (Klassenvariable).	
	private static final int ACC_FINAL = 0x0010; // Kann nicht abgeleitet werden.
	private static final int ACC_SUPER = 0x0020; // Behandelt Methodenaufrufe der Superklasse speziell. Dieses
												 // Flag dient zur Rueckwaertskompatibilitaet und wird von neueren
												 // Compilern immer gesetzt.
	private static final int ACC_VOLATILE = 0x0040; // Kann nicht ge-cached werden.
	private static final int ACC_TRANSIENT = 0x0080; // Feld als transient deklariert.
	private static final int ACC_NATIVE = 0x0100; // In einer anderen Sprache (als Java) implementiert.
	private static final int ACC_INTERFACE = 0x0200; // Dieses Flag ist gesetzt, wenn es sich um ein Interface und
													// nicht um eine Klasse handelt.
	private static final int ACC_ABSTRACT = 0x0400; // Kann nicht instanziert werden.
	private static final int ACC_STRICT = 0x0800; // Als strictfp deklariert.
	
	
	private static FormattedStringBuilder sb = new FormattedStringBuilder();
	
	public static boolean VERBOSE = true;
	
	public static void main(String[] args) {
		run(BA);
		byte[] ba2 = ClassBuilderSimple.build("MySubClass", "MySuperClass");
		run(ba2);
	}

	private static void run(byte[] ba) {
		ByteBuffer bb = ByteBuffer.wrap(ba);
		
		logHex("Magic:", bb.get(), bb.get(), bb.get(), bb.get());
		log("Version:", bb.getShort(), bb.getShort());
		int poolSize = bb.getShort();
		log("Pool size:", poolSize);
		for (int i = 1; i < poolSize; i++) {
			int tag = bb.get();
			CP cp = CP.values()[tag];
			log("entry=" + i + ":", Integer.toString(tag), cp.name());
			switch(cp) {
			case CONSTANT_Utf8: {
				int len = bb.getShort();
				sb.fill(20);
				for (int c = 0; c < len; c++) {
					sb.append((char)bb.get());
				}
				sb.appendln();
				break;
			}
			case CONSTANT_Class: {
				int id = bb.getShort();
				log("     ID=", id);
				break;
			}
			case CONSTANT_Methodref: {
				int idClass = bb.getShort();
				int idType = bb.getShort();
				log("     classID=", idClass + " typeNameID=" + idType);
				break;
			}
			case CONSTANT_NameAndType: {
				int idName = bb.getShort();
				int idType = bb.getShort();
				log("     nameID=", idName + " typeID=" + idType);
				break;
			}
			default: throw new UnsupportedOperationException(cp.name());
			}
		}
		sb.appendln("p=" + bb.position());
		
		sb.appendln();
		sb.appendln("Class descriptor");
		sb.appendln("================");
		int classMods = bb.getShort();
		sb.append("Modifiers:").fill(20);
		getModifiers(classMods, true);
		sb.appendln();
		
		sb.append("Name:").fill(20);
		int thisID = bb.getShort();
		sb.appendln("ID=" + thisID);
		int superID = bb.getShort();
		sb.append("Super-class").fill(20);
		sb.appendln("ID=" + superID);
		int nInter = bb.getShort();
		sb.append("Interfaces").fill(20);
		sb.appendln("n=" + nInter);
		
		sb.appendln();
		sb.appendln("Fields");
		sb.appendln("================");
		int nFields = bb.getShort();
		sb.append("Fields").fill(20);
		sb.appendln("n=" + nFields);
		
		sb.appendln();
		sb.appendln("Methods");
		sb.appendln("================");
		int nMethods = bb.getShort();
		sb.append("Methods").fill(20);
		sb.appendln("n=" + nMethods);
		for (int c = 0; c < nMethods; c++) {
			int mods = bb.getShort();
			sb.append("Method").fill(20);
			getModifiers(mods, false);
			int nameID = bb.getShort();
			sb.append("nameID=" + nameID);
			int signID = bb.getShort();
			sb.append("  signatureID=" + signID);
			sb.appendln();
			sb.fill(20);
			int nAttr = bb.getShort();
			sb.append("attributes=" + nAttr);
			sb.appendln();

			for (int a = 0; a < nAttr; a++) {
				int attrID = bb.getShort();
				int attrLen = bb.getInt();
				byte[] mba = new byte[attrLen]; 
				bb.get(mba);
				sb.fill(20); 
				sb.append("ID=" + attrID);
				sb.append("  len=" + attrLen);
				sb.append("  code=" + Arrays.toString(mba));
				sb.appendln();
			}
		}
		
		sb.appendln();
		sb.appendln("Class attributes");
		sb.appendln("================");
		int nClassAttr = bb.getShort();
		sb.append("Attributes").fill(20);
		sb.appendln("n=" + nClassAttr);
		for (int a = 0; a < nClassAttr; a++) {
			int attrID = bb.getShort();
			int attrLen = bb.getInt();
			byte[] mba = new byte[attrLen]; 
			bb.get(mba);
			sb.fill(20); 
			sb.append("ID=" + attrID);
			sb.append("  len=" + attrLen);
			sb.append("  code=" + Arrays.toString(mba));
			sb.appendln();
		}

		
//		int classMods = bb.getShort();
//		sb.append("Modifiers:").fill(20);
//		if ((classMods & ACC_PUBLIC) != 0) sb.append("public ");
//		if ((classMods & ACC_FINAL) != 0) sb.append("final ");
//		if ((classMods & ACC_SUPER) != 0) sb.append("super ");
//		if ((classMods & ACC_ABSTRACT) != 0) sb.append("abstract ");
//		if ((classMods & ACC_INTERFACE) != 0) sb.append("interface ");
//		else sb.append("class ");
//		sb.appendln();
//		sb.append("Name:").fill(20);
//		int thisID = bb.getShort();
//		sb.appendln("ID=" + thisID);
//		int superID = bb.getShort();
//		sb.append("Super-class").fill(20);
//		sb.appendln("ID=" + superID);
//		int nInter = bb.getShort();
//		sb.append("Interfaces").fill(20);
//		sb.appendln("n=" + nInter);
		
		sb.appendln("p=" + bb.position() + "/" + ba.length);
		if (VERBOSE) {
			System.out.println(sb);
		}
	}


	private static void getModifiers(int mods, boolean isClass) {
		if ((mods & ACC_PUBLIC) != 0) sb.append("public ");
		if ((mods & ACC_PRIVATE) != 0) sb.append("private ");
		if ((mods & ACC_PROTECTED) != 0) sb.append("protected ");
		if ((mods & ACC_STATIC) != 0) sb.append("static ");
		if ((mods & ACC_FINAL) != 0) sb.append("final ");
		if (isClass) {
			if ((mods & ACC_SUPER) != 0) sb.append("super ");
		} else {
			if ((mods & ACC_SUPER) != 0) sb.append("synchronized ");
		}
		if ((mods & ACC_ABSTRACT) != 0) sb.append("abstract ");
		if (isClass) {
			if ((mods & ACC_INTERFACE) != 0) sb.append("interface ");
			else sb.append("class ");
		}
	}
	
	private static void logHex(String string, byte ... bytes) {
		sb.append(string).fill(20);
		for (byte b: bytes) {
			sb.append(toHex(b));
			sb.append(" ");
		}
		sb.appendln();
	}
	
	private static void log(String string, int ... values) {
		sb.append(string).fill(20);
		for (int v: values) {
			sb.append(v);
			sb.append(" ");
		}
		sb.appendln();
	}
	
	private static void log(String string, String ... values) {
		sb.append(string).fill(20);
		for (String v: values) {
			sb.append(v);
			sb.append(" ");
		}
		sb.appendln();
	}
	
	private static String toHex(byte b) {
		String s = Integer.toHexString(b);
		return s.substring(6);
	}
	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy