Artifact cac47d1bc9e11d3ff0d9e0da5ad9114cbe07b0034caa1f74e3765a19d9344379:
- Executable file
r37/lisp/csl/jlisp/ClassDescription.java
— part of check-in
[f2fda60abd]
at
2011-09-02 18:13:33
on branch master
— Some historical releases purely for archival purposes
git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/trunk/historical@1375 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 37657) [annotate] [blame] [check-ins using] [more...]
// Date: 09/02/02 // Name: Vijay P. Chauhan // Supervisor: Dr. Arthur Norman // "Jlisp to JVM Compiler" - Part II Project // // 21/02/02 // ClassDescription4.java for using with jlisp to make LengthFn.class // ClassDescription3.java THIS IS FOR getting resolveAll() to work // ClassDescription2.java works fine (with one cheat). // resolveAll wasn't working because I was casting to Code_attribute // needed to access attribute[].info with offset 8(maxstack,locals,length,etc) // Class File format (.class) mapped out according to JVM spec // map structure -> byte[] -> written to file (.class) import java.util.*; import java.io.*; import java.lang.reflect.*; public class ClassDescription { // all access flags included for COMPLETENESS even though not all used public static final short ACC_DEFAULT = 0x0000; public static final short ACC_PUBLIC = 0x0001; public static final short ACC_PRIVATE = 0x0002; public static final short ACC_PROTECTED = 0x0004; public static final short ACC_STATIC = 0x0008; public static final short ACC_FINAL = 0x0010; public static final short ACC_SYNCHRONIZED = 0x0020; public static final short ACC_SUPER = 0x0020; public static final short ACC_VOLATILE = 0x0040; public static final short ACC_TRANSIENT = 0x0080; public static final short ACC_NATIVE = 0x0100; public static final short ACC_INTERFACE = 0x0200; public static final short ACC_ABSTRACT = 0x0400; public static final short ACC_STRICT = 0x0800; // check if versions supported by jdk1.4.0 beta3 // Note that I REALLY HOPE that the code here is not sensitive to // just which release of Java is in use. Thre is no good reason why // it should be! static final int MAGIC = 0xcafebabe; static final short minor_version = 0x0; static final short major_version = 0x2e; short constant_pool_count = 0; Cp_info constant_pool[]; short access_flags; short this_class; //= 14 short super_class; //= 7 short interfaces_count = 0; // counts are initialised to 0 short interfaces[]; //should be [interfaces_count] short fields_count = 0; Field_info fields[]; //should be [fields_count] short methods_count = 0; Method_info methods[]; //should be [methods_count] short attributes_count = 0; //LineNumberTable, SourceFile not implmtd Attribute_info attributes[] ; //should be [attributes_count] //NOT part of classfile structure -> see VM spec for above String thisString; String superString = "java/lang/Object"; String init = "<init>"; String code = "Code"; String exceptions_attribute = "Exceptions"; String exception = "java/lang/Exception"; short this_Utf8, super_Utf8, code_Utf8; short globalIndex; short initNAT, initref; //for holding reference to methodref_info for <init> Exceptions_attribute ea = new Exceptions_attribute(); byte[] ClassBytes; // note from ACN to VPC. There is a Java tradition of naming little // methods that just set a field xxx as setxxx. void mNumber(int a) //number of methods defined in the class //N.B. which is NOT necessarily equal to number of methodref_infos { methods = new Method_info[a]; } void setAccess(short access) { access_flags = access; } void addCode() throws IOException { addUtf8(code); code_Utf8 = globalIndex; } //put "Code" for Code_attribute in cp[1] since cp[0] is null void addExceptions() throws IOException { addUtf8(exceptions_attribute); //put "Exceptions" for Exceptions_attribute in cp[2] ea.attribute_name_index = globalIndex; //put "java/lang/Exception" in cp[3] addUtf8(exception); addCInfo(globalIndex); ea.exception_index_table[0] = globalIndex; ea.toInfo(); } void setThis(String thisName) throws UnsupportedEncodingException, IOException { thisString = thisName; addUtf8(thisName); //add CONSTANT_Utf8_info this_Utf8 = globalIndex; addCInfo(this_Utf8); //add CONSTANT_Class_info this_class = globalIndex; // put thisName in ConstantPool and then set this_class } void setSuper() throws UnsupportedEncodingException, IOException { addUtf8(superString); //add CONSTANT_Utf8_info super_Utf8 = globalIndex; addCInfo(super_Utf8); //add CONSTANT_Class_info super_class = globalIndex; //if no argument given then default superclass is java.lang.Object } void setSuper(String superName) throws UnsupportedEncodingException, IOException { superString = superName; addUtf8(superString); //add CONSTANT_Utf8_info super_Utf8 = globalIndex; addCInfo(super_Utf8); //add CONSTANT_Class_info super_class = globalIndex; // put superString in ConstantPool } void addInit(Method_info m1) throws IOException // how to add <init>, ()V since needed for every class { m1.setAccess((short)ACC_PUBLIC); // ACC_PUBLIC in some cases? //make <init> PUBLIC by default lookupUtf8(init); // DO NOT ASSUME THERE IS ONLY 1 "<init>" made. if (utf8Index == 0) // not made so far { addUtf8(init); // then make it m1.name_index = globalIndex; } else m1.name_index = utf8Index; addUtf8("()V"); //"()V" m1.descriptor_index = globalIndex; addNAT(m1); initNAT = globalIndex; //addCInfo(super_Utf8); //invoked from super_class (whatever it is) //super_class = globalIndex; //7 addCMInfo(super_class, initNAT); initref = globalIndex; /* addUtf8("<init>"); //"<init>" m1.name_index = globalIndex; //4 addUtf8("()V"); //"()V" m1.descriptor_index = globalIndex; //5 addNAT(m1); NATindex = globalIndex; //6 //addCInfo(super_Utf8); //invoked from super_class (whatever it is) //super_class = globalIndex; //7 addCMInfo(super_class, NATindex); */ // m1.attributes_count = (short)1; fixed in Method_info.java Code_attribute ca1 = new Code_attribute(); ca1.attribute_name_index = code_Utf8; ca1.setStackLocals((short)1,(short)1); ca1.addInstruction(ByteCodes.ALOAD_0); //lookupRef("<init>", ca1); //no need to lookup really? save time? //byte[] arg1 = ByteArray.shortToByteArray(methodrefIndex[0]);//{0x00, 0x08}; //cp[8] //byte[] arg1 = ByteArray.shortToByteArray(refIndex); byte[] arg1 = ByteArray.shortToByteArray(initref); ca1.addInstruction(ByteCodes.INVOKESPECIAL, arg1); ca1.addInstruction(ByteCodes.RETURN); ca1.toInfo(); m1.attributes = new Attribute_info[m1.attributes_count]; m1.attributes[0] = ca1; methods[methods_count++] = m1; } void addMethod(Method_info m3, String methodName, String methodDesc) throws IOException // makes Methodref_info irrespective -> see other addMethod(...,boolean b) { //m3.setAccess((short)(ClassDescription4.ACC_STATIC)); addUtf8(methodName); m3.name_index = globalIndex; addUtf8(methodDesc); // argument and result types, eg "(I)I" m3.descriptor_index = globalIndex; addNAT(m3); //addCInfo(this_Utf8); // NOT super_class but this_class //any method after <init> (not 'main') has this_class as class_index //this_class = globalIndex; addCMInfo(this_class, globalIndex); } void addMethod(Method_info m3, String methodName, String methodDesc, boolean b) throws IOException // if (b==true) then it means we do want a Methodref too, otherwise not { addUtf8(methodName); m3.name_index = globalIndex; addUtf8(methodDesc); // eg "(I)I" m3.descriptor_index = globalIndex; if (b) { addNAT(m3); addCMInfo(this_class, globalIndex); } } Vector cptemp = new Vector(20,10); //default size 20, increment 10 if full. //change to more appropriate numbers depending on likely cp size. //process of incrementing takes time (see Java 2-Ivor Horton, pg 410). //possible optimisation HERE void addMethodref(String cl, String nm, String des) throws IOException { short nmidx; short desidx; Code_attribute ca = new Code_attribute(); lookupCinfo(cl,ca, false); // don't want to add to toResolveClass list if (cinfoIndex == 0) // if no class entry by this name.. { addUtf8(cl); // ..then create one addCInfo(globalIndex); cinfoIndex = globalIndex; } lookupUtf8(nm); if (utf8Index == 0) // not made so far { addUtf8(nm); // then make it nmidx = globalIndex; } else nmidx = utf8Index; lookupUtf8(des); if (utf8Index == 0) // not made so far { addUtf8(des); // then make it desidx = globalIndex; } else desidx = utf8Index; if (!isNAT(nmidx, desidx)) { addNAT(nmidx, desidx); addCMInfo(cinfoIndex, globalIndex); } else if (!isRef(cinfoIndex, nameAndTypeIndex)) { addCMInfo(cinfoIndex, nameAndTypeIndex); } // else System.out.print("**************NO NEED TO MAKE MREF"); utf8Index = 0; nameAndTypeIndex = 0; cinfoIndex = 0; // before anyone else uses this value again } void addFieldref(String cl, String nm, String des) throws IOException { short nmidx; short desidx; Code_attribute ca = new Code_attribute(); lookupCinfo(cl,ca, false); // don't want to add to toResolveClass list if (cinfoIndex == 0) // if no class entry by this name.. { addUtf8(cl); // ..then create one addCInfo(globalIndex); cinfoIndex = globalIndex; } lookupUtf8(nm); if (utf8Index == 0) // not made so far { addUtf8(nm); // then make it nmidx = globalIndex; } else nmidx = utf8Index; lookupUtf8(des); if (utf8Index == 0) // not made so far { addUtf8(des); // then make it desidx = globalIndex; } else desidx = utf8Index; if (!isNAT(nmidx, desidx)) { addNAT(nmidx, desidx); addCFInfo(cinfoIndex, globalIndex); } else if (!isRef(cinfoIndex, nameAndTypeIndex)) { addCFInfo(cinfoIndex, nameAndTypeIndex); } //else System.out.print("**************NO NEED TO MAKE FREF") utf8Index = 0; nameAndTypeIndex = 0; cinfoIndex = 0; // before anyone else uses this value again } void addClassInfo(String cl)throws IOException { Code_attribute ca = new Code_attribute(); lookupCinfo(cl,ca,false); if (cinfoIndex == 0) // if no class entry by this name.. { addUtf8(cl); // ..then create one addCInfo(globalIndex); } } void addCFInfo(short classindex, short NATindex) throws IOException { CONSTANT_Fieldref_info cf = new CONSTANT_Fieldref_info(classindex, NATindex); addToCP(cf); } void addCMInfo(short classindex, short NATindex) throws IOException { CONSTANT_Methodref_info cm = new CONSTANT_Methodref_info(classindex, NATindex); addToCP(cm); } void addCInfo(short classindex) throws IOException { CONSTANT_Class_info ci = new CONSTANT_Class_info(classindex); addToCP(ci); } void addNAT(short nidx, short didx) throws IOException // if Methodref/Fieldref_info not associated with declared method/field { CONSTANT_NameAndType_info cnt = new CONSTANT_NameAndType_info(nidx, didx); addToCP(cnt); } void addNAT(Method_info m) throws IOException // NEED one for Field_info? in future maybe if Field_info needed. { CONSTANT_NameAndType_info cnt = new CONSTANT_NameAndType_info(m.name_index, m.descriptor_index); addToCP(cnt); } void addUtf8(String s) throws IOException { CONSTANT_Utf8_info cu = new CONSTANT_Utf8_info(s); addToCP(cu); } void addToCP(Cp_info c) { cptemp.add(c); globalIndex = (short)(cptemp.indexOf(c)+1); //very important: globalIndex //or just do globalIndex++ ? //+1 because CP entries start from cp[1], not from cp[0] } Vector labels = new Vector(); Vector positions = new Vector(); Vector mcountsL = new Vector(); Vector labelToLookup = new Vector(); Vector positionToPut = new Vector(); void setLabel(String label, Code_attribute ca) { labels.add(label); Integer pointer = new Integer(ca.code.length); positions.add(pointer); Short methodIndex = new Short(methods_count); mcountsL.add(methodIndex); } void lookupLabel(String label, Code_attribute ca) { labelToLookup.add(label); Integer pointer = new Integer(ca.code.length+1); positionToPut.add(pointer); //because GOTO or IF_CMP instr not yet added } void resolveLabels() //only one pass overall { for (int i=0; i<labelToLookup.size(); i++) { for (int j=0; j<labels.size(); j++) { if (labelToLookup.get(i) == labels.get(j)) { //Jlisp.println("i = " + i + " j = " + j); //Jlisp.println(positions.size() + " " + positionToPut.size() + " " + //mcountsL.size() + " " + methods.length); int offset = ((Integer)positions.get(j)).intValue() - ((Integer)positionToPut.get(i)).intValue() + 1; byte[] bytesoffset = ByteArray.shortToByteArray((short)offset); int pointer = ((Integer)positionToPut.get(i)).intValue(); short methodIndex = ((Short)mcountsL.get(j)).shortValue(); // ACN changed the above from i to j ^ (methods[methodIndex].attributes[0]).info[pointer+8]=bytesoffset[0]; (methods[methodIndex].attributes[0]).info[pointer+8+1]=bytesoffset[1]; break; //don't need to check anymore } } } } short refIndex = (short)0; //check when these indexes change short cinfoIndex = (short)0; short utf8Index = (short)0; short nameAndTypeIndex =(short)0; short mfRefIndex = (short)0; int resolveFlag = 0; //check when changes and when changes back (Per loop) boolean isRef(short cl, short nat) throws UnsupportedEncodingException, IOException { Vector cptemp1 = cptemp; Vector frefs = new Vector(); Vector mrefs = new Vector(); Vector FRefs = new Vector(); Vector MRefs = new Vector(); mfRefIndex = (short)0; //in case changed somewhere before for (int i=0; i<cptemp1.size(); i++) { Cp_info cpEntry = (Cp_info)cptemp1.get(i); Short presentIndex = new Short((short)(i+1)); if (cpEntry.tag == (byte)0x9) //fref { frefs.add(cpEntry); FRefs.add(presentIndex); } else if (cpEntry.tag == (byte)0xa) //mref { mrefs.add(cpEntry); MRefs.add(presentIndex); } } for (int k=0; k<frefs.size(); k++) { CONSTANT_Fieldref_info cpEntry = (CONSTANT_Fieldref_info)frefs.get(k); if ((cpEntry.class_index == cl) & (cpEntry.name_and_type_index == nat)) { mfRefIndex = ((Short)FRefs.get(k)).shortValue(); return true; } } for (int j=0; j<mrefs.size(); j++) { CONSTANT_Methodref_info cpEntry = (CONSTANT_Methodref_info)mrefs.get(j); if ((cpEntry.class_index == cl) & (cpEntry.name_and_type_index == nat)) { mfRefIndex = ((Short)MRefs.get(j)).shortValue(); return true; } } return false; } boolean isNAT(short nm, short des) throws UnsupportedEncodingException, IOException { Vector cptemp1 = cptemp; for (int i=0; i<cptemp1.size(); i++) { Cp_info cpEntry = (Cp_info)cptemp1.get(i); short presentIndex = (short)(i+1); if (cpEntry.tag == (byte)0xc) //NAT_info { CONSTANT_NameAndType_info natEntry = (CONSTANT_NameAndType_info)cpEntry; if ((natEntry.name_index == nm) & (natEntry.descriptor_index == des)) { nameAndTypeIndex = presentIndex; //System.out.println("************FOUND A NAT MATCH"); return true; } } } return false; } void lookupUtf8(String utf8) throws UnsupportedEncodingException, IOException { Vector cptemp1 = cptemp; Vector utf8s = new Vector(); //vectors for holding cp_info itself Vector Utf8s = new Vector(); //vectors for holding cp-indexes //System.out.println(cptemp1.size()+" CP entries"); for (int i=0; i<cptemp1.size(); i++) { Cp_info cpEntry = (Cp_info)cptemp1.get(i); Short presentIndex = new Short((short)(i+1)); // i.e. give cp-index, not vector index by i+1... // ...because first entry in CP is cp[1] NOT cp[0] switch (cpEntry.tag) { case (byte)0x1: //Utf8_info utf8s.add(cpEntry); //System.out.println(presentIndex+ " we have a utf8"); Utf8s.add(presentIndex); break; default: break; } } short index = (short)-1; for (int i=0; i<utf8s.size(); i++) { CONSTANT_Utf8_info cpEntry = (CONSTANT_Utf8_info)utf8s.get(i); String compare = new String(cpEntry.bytes, "UTF-8"); //System.out.println(utf8 + " == " + compare+" ?"); if (utf8.equals(compare)) { index = ((Short)Utf8s.get(i)).shortValue(); //System.out.println("Hello. we got UTF8 match. Index no. "+index); break; // assume there is only one match or no match } } if (index == (short)-1) // i.e. no utf8 matches found utf8Index = 0; // in case this value has been changed else utf8Index = index; } void lookupCinfo(String classname, Code_attribute ca, boolean b) // just like lookupRef throws UnsupportedEncodingException, IOException { Vector cptemp1 = cptemp; Vector utf8s = new Vector(); //vectors for holding cp_info itself Vector classes = new Vector(); Vector Utf8s = new Vector(); //vectors for holding cp-indexes Vector Classes = new Vector(); //System.out.println(cptemp1.size()+" CP entries"); for (int i=0; i<cptemp1.size(); i++) { Cp_info cpEntry = (Cp_info)cptemp1.get(i); Short presentIndex = new Short((short)(i+1)); // i.e. give cp-index, not vector index by i+1... // ...because first entry in CP is cp[1] NOT cp[0] switch (cpEntry.tag) { case (byte)0x1: //Utf8_info utf8s.add(cpEntry); //System.out.println(presentIndex+ " we have a utf8"); Utf8s.add(presentIndex); break; case (byte)0x7: //class_info classes.add(cpEntry); //System.out.println(presentIndex+ " we have a class"); Classes.add(presentIndex); break; default: break; } } short index = (short)-1; for (int i=0; i<utf8s.size(); i++) { CONSTANT_Utf8_info cpEntry = (CONSTANT_Utf8_info)utf8s.get(i); String compare = new String(cpEntry.bytes, "UTF-8"); //System.out.println(classname + " == " + compare+" ?"); if (classname.equals(compare)) { index = ((Short)Utf8s.get(i)).shortValue(); //System.out.println("Hello. we got a match. Index no. "+index); break; // assume there is only one match or no match } } if (index == (short)-1) //i.e. no utf8 matches found { cinfoIndex = 0; //in case this value has been changed if (b) addToResolveClass(classname, ca); return; } else { for (int i=0; i<classes.size(); i++) { CONSTANT_Class_info cpEntry = (CONSTANT_Class_info)classes.get(i); if (cpEntry.name_index == index) { cinfoIndex = ((Short)Classes.get(i)).shortValue(); //System.out.println("Class_info match. index no. "+cinfoIndex); break; //assume only one match for NAT or no match } } } } void lookupRef(String name, Code_attribute ca) //works for field_info as well as method_info (I hope) throws UnsupportedEncodingException, IOException { Vector cptemp1 = cptemp; Vector utf8s = new Vector(); //vectors for holding cp_info itself Vector nats = new Vector(); Vector mrefs = new Vector(); Vector classes = new Vector(); Vector frefs = new Vector(); Vector Utf8s = new Vector(); //vectors for holding cp-indexes Vector Nats = new Vector(); Vector Mrefs = new Vector(); Vector Classes = new Vector(); Vector Frefs = new Vector(); //System.out.println(cptemp1.size()+" CP entries"); for (int i=0; i<cptemp1.size(); i++) { Cp_info cpEntry = (Cp_info)cptemp1.get(i); Short presentIndex = new Short((short)(i+1)); // i.e. give cp-index, not vector index by i+1... // ...because first entry in CP is cp[1] NOT cp[0] switch (cpEntry.tag) { case (byte)0x1: //Utf8_info utf8s.add(cpEntry); Utf8s.add(presentIndex); break; case (byte)0xc: //nat_info nats.add(cpEntry); Nats.add(presentIndex); break; case (byte)0xa: //mref_info mrefs.add(cpEntry); Mrefs.add(presentIndex); break; case (byte)0x7: //class_info classes.add(cpEntry); Classes.add(presentIndex); break; case (byte)0x9: //fieldref_info frefs.add(cpEntry); Frefs.add(presentIndex); break; default: //System.out.println("some other type of Cp_info?"); break; } } short index = (short)-1; short natIndex = (short)-1; short mrefidx = (short)-1; for (int i=0; i<utf8s.size(); i++) { CONSTANT_Utf8_info cpEntry = (CONSTANT_Utf8_info)utf8s.get(i); String compare = new String(cpEntry.bytes, "UTF-8"); //System.out.println(name + " == " + compare+" ?"); if (name.equals(compare)) { index = ((Short)Utf8s.get(i)).shortValue(); //System.out.println("Hello. we got a match. Index no. "+index); break; // assume there is only one match or no match } } if (index == (short)-1) //i.e. no utf8 matches found { if (resolveFlag == 0) { addToResolveList(name, ca); refIndex = (short)0; //incase it contains a value from previous call //System.out.println("this method/field not found...so far"); return; //i.e. return from method if no utf8 match } else //i.e. part of resolveAll() so addToResolveList() already done //System.out.println("ERROR! Method "+name+" was NEVER declared") ; } //ASSUMPTION: there are no fields (or other utf8s) by same name as method //if there is a field then next stage would find a fieldref //and say we can't cast to Methodref_info as a result else { for (int i=0; i<nats.size(); i++) { CONSTANT_NameAndType_info cpEntry = (CONSTANT_NameAndType_info)nats.get(i); if (cpEntry.name_index == index) { natIndex = ((Short)Nats.get(i)).shortValue(); //System.out.println("NAT match. Natindex no. "+natIndex); if (natIndex == initNAT) continue; //continue with loop and look for next match else break; } } } if (natIndex == (short)-1) { //System.out.println("name "+name+" not a method(or maybe 'main'"); return; } //ASSUMPTION: we are not going to have overloaded methods //otherwise need to check that type descriptor matches too //also assume there is NOT both methodref+fieldref for any string else { for(int i=0; i<mrefs.size(); i++) { CONSTANT_Methodref_info cpEntry = (CONSTANT_Methodref_info)mrefs.get(i); if (cpEntry.name_and_type_index == natIndex) { mrefidx = ((Short)Mrefs.get(i)).shortValue(); //System.out.println("Methodref_info MATCH! no. "+mrefidx); refIndex=mrefidx; } } for(int i=0; i<frefs.size(); i++) { CONSTANT_Fieldref_info cpEntry = (CONSTANT_Fieldref_info)frefs.get(i); if (cpEntry.name_and_type_index == natIndex) { mrefidx = ((Short)Frefs.get(i)).shortValue(); //System.out.println("Fieldref_info MATCH! no. "+mrefidx); refIndex=mrefidx; } } } if (mrefidx == (short)-1) //i.e. couldn't find the mref_idx //System.out.println("something wrong? utf8, NAT but no methodref") ; } void printCP() //prints out contents of final CP entries //makes use of lookup...() technology throws UnsupportedEncodingException, IOException { Vector cptemp1 = cptemp; Vector utf8s = new Vector(); //vectors for holding cp_info itself Vector nats = new Vector(); Vector mrefs = new Vector(); Vector classes = new Vector(); Vector frefs = new Vector(); Vector Utf8s = new Vector(); //vectors for holding cp-indexes Vector Nats = new Vector(); Vector Mrefs = new Vector(); Vector Classes = new Vector(); Vector Frefs = new Vector(); //System.out.println(cptemp1.size()+" CP entries"); for (int i=0; i<cptemp1.size(); i++) { Cp_info cpEntry = (Cp_info)cptemp1.get(i); Short presentIndex = new Short((short)(i+1)); //i.e. give cp-index, not vector index by i+1... //...because first entry in CP is cp[1] NOT cp[0] switch (cpEntry.tag) { case (byte)0x1: //Utf8_info utf8s.add(cpEntry); CONSTANT_Utf8_info cpEntry1 = (CONSTANT_Utf8_info)cpEntry; String utf8name = new String(cpEntry1.bytes, "UTF-8"); //System.out.println("cp["+presentIndex+ "]\tutf8:\t"+utf8name); Utf8s.add(presentIndex); break; case (byte)0xc: //nat_info nats.add(cpEntry); CONSTANT_NameAndType_info cpEntry2 = (CONSTANT_NameAndType_info)cpEntry; short nmix = cpEntry2.name_index; short tyix = cpEntry2.descriptor_index; //System.out.println("cp["+presentIndex+ "]\tnat:\t"+ // nmix+","+tyix); Nats.add(presentIndex); break; case (byte)0xa: //mref_info mrefs.add(cpEntry); CONSTANT_Methodref_info cpEntry3 = (CONSTANT_Methodref_info)cpEntry; short clix = cpEntry3.class_index; short ntix = cpEntry3.name_and_type_index; //System.out.println("cp["+presentIndex+ "]\tmref:\t"+clix+","+ntix); Mrefs.add(presentIndex); break; case (byte)0x7: //class_info classes.add(cpEntry); CONSTANT_Class_info cpEntry4 = (CONSTANT_Class_info)cpEntry; nmix = cpEntry4.name_index; //System.out.println("cp["+presentIndex+ "]\tclass:\t"+nmix); Classes.add(presentIndex); break; case (byte)0x9: //fieldref_info frefs.add(cpEntry); CONSTANT_Fieldref_info cpEntry5 = (CONSTANT_Fieldref_info)cpEntry; clix = cpEntry5.class_index; ntix = cpEntry5.name_and_type_index; //System.out.println("cp["+presentIndex+ "]\tfref:\t"+ // clix+","+ntix); Frefs.add(presentIndex); break; default: //System.out.println("some other type of Cp_info?"); break; } } } Vector toResolve = new Vector(); // hold names to be resolved Vector mcounts = new Vector(); // which methods[i] it appears in Vector pointers = new Vector(); // which bit of code to be changed void addToResolveList(String name, Code_attribute ca) { toResolve.add(name); //method name to be resolved Short methodIndex = new Short(methods_count); mcounts.add(methodIndex); //which method the code appears in Integer pointer = new Integer(ca.code.length); //length is where you //got upto before when the cp index was needed and NOT resolved pointers.add(pointer);//pointer to which code to be amended //Vector of strings to resolve, with index of where to update in code. } Vector toResolveC = new Vector(); // hold names to be resolved Vector mcountsC = new Vector(); // which methods[i] it appears in Vector pointersC = new Vector(); // which bit of code to be changed void addToResolveClass(String name, Code_attribute ca) //for resolving class_infos { toResolveC.add(name); //method name to be resolved Short methodIndex = new Short(methods_count); mcountsC.add(methodIndex); //which method the code appears in Integer pointer = new Integer(ca.code.length); //length is where you //got upto before when the cp index was needed and NOT resolved pointersC.add(pointer);//pointer to which code to be amended //Vector of strings to resolve, with index of where to update in code. } void resolveAll() throws IOException, UnsupportedEncodingException { //System.out.println("*****NUMBER OF REFS TO RESOLVE IS: "+toResolve.size()); for (int i=0; i<toResolve.size(); i++) { resolveFlag = 1; //to say that this is resolveAll() Code_attribute ca = new Code_attribute(); // made purely for passing on to satisfy parameter requirements // of lookupMref lookupRef((String)toResolve.get(i), ca); byte[] newIndex = ByteArray.shortToByteArray(refIndex); int pointer = ((Integer)pointers.get(i)).intValue(); short methodIndex = ((Short)mcounts.get(i)).shortValue(); (methods[methodIndex].attributes[0]).info[pointer+8+1]=newIndex[0]; (methods[methodIndex].attributes[0]).info[pointer+8+2]=newIndex[1]; } //System.out.println("RESOLVE-REFS ALL DONE"); //System.out.println("*****NUMBER OF CINFOS TO RESOLVE IS: "+toResolveC.size()); for (int i=0; i<toResolveC.size(); i++) { Code_attribute ca = new Code_attribute(); lookupCinfo((String)toResolveC.get(i), ca, false); byte[] newIndex = ByteArray.shortToByteArray(cinfoIndex); int pointer = ((Integer)pointersC.get(i)).intValue(); short methodIndex = ((Short)mcountsC.get(i)).shortValue(); (methods[methodIndex].attributes[0]).info[pointer+8+1]=newIndex[0]; (methods[methodIndex].attributes[0]).info[pointer+8+2]=newIndex[1]; } //System.out.println("RESOLVE-CLASSES ALL DONE"); resolveLabels(); } //NEED RESOLVE TO DEAL WITH CLASSINFO too: void makeCP() throws UnsupportedEncodingException { cptemp.trimToSize(); //no need for this? capacity vs. size constant_pool_count = (short)(cptemp.size()+1); //System.out.println("constant_pool_count = " + constant_pool_count); constant_pool = new Cp_info[constant_pool_count-1]; for (int i=0; i<cptemp.size(); i++) { constant_pool[i] = (Cp_info)(cptemp.get(i)); // System.out.println("\n\n" + i); // constant_pool[i].printBytes(constant_pool[i].dumpBytes()); } } byte[] dumpBytes() { byte[][] Bytes = new byte[13][0]; Bytes[0] = ByteArray.intToByteArray(MAGIC); Bytes[1] = ByteArray.shortToByteArray(minor_version); Bytes[2] = ByteArray.shortToByteArray(major_version); Bytes[3] = ByteArray.shortToByteArray(constant_pool_count); Bytes[4] = ByteArray.cpToByteArray(constant_pool); Bytes[5] = ByteArray.shortToByteArray(access_flags); Bytes[6] = ByteArray.shortToByteArray(this_class); Bytes[7] = ByteArray.shortToByteArray(super_class); Bytes[8] = ByteArray.shortToByteArray(interfaces_count); // ignore interfaces[] since never likely to need it Bytes[9] = ByteArray.shortToByteArray(fields_count); Bytes[10] = ByteArray.shortToByteArray(methods_count); Bytes[11] = ByteArray.miToByteArray(methods); Bytes[12] = ByteArray.shortToByteArray(attributes_count); //Bytes[13] = attributes[0].dumpBytes(); // Bytes[16] = ByteArray.byteToByteArray((byte)0); // Is zero at end of class file? (eof marker?) ClassBytes = ByteArray.flatBytes(Bytes); return ClassBytes; } //writes byte array to a file void bytesToFile(byte[] Bytes) throws IOException, FileNotFoundException { //File f1 = new File("D:/jlisp/MyCode/"+thisString+".class"); File f1 = new File("./"+thisString+".class"); DataOutputStream outStream = new DataOutputStream( new BufferedOutputStream( new FileOutputStream(f1))); for (int i=0; i<Bytes.length; i++) outStream.writeByte(Bytes[i]); outStream.close(); } Object loadCF() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { // This loads a class using the current CLASSPATH... JlispClassLoader loader = new JlispClassLoader(); Object r = loader.loadMyInstance(thisString); //System.out.println("Object = " + r + " of type " + r.getClass()); return r; } Object instanceFromBytes() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { // Load a class from an array of bytes and create an instance of it. // byte [] bytes = dumpBytes(); //no need to...ClassBytes JlispClassLoader loader = new JlispClassLoader(); Object r = loader.loadMyInstance(thisString, ClassBytes); //System.out.println("Object = " + r + " of type " + r.getClass()); return r; } } // end of ClassDescription.java