1 package alt.jiapi.tool; 2 3 import java.lang.reflect.Modifier ; 4 import java.io.IOException ; 5 import java.util.List ; 6 import java.util.Iterator ; 7 8 import alt.jiapi.file.*; 9 import alt.jiapi.reflect.*; 10 import alt.jiapi.reflect.instruction.*; 11 12 18 public class ClassDiff { 19 private ClassFile f1; 20 private ClassFile f2; 21 22 public static void main(String [] args) throws IOException { 23 if (args.length != 2) { 24 System.out.println("Usage: ClassDiff <file1.class> <file2.class>"); 25 System.exit(0); 26 } 27 28 ClassDiff cd = new ClassDiff(args[0], args[1]); 29 cd.runDiff(); 30 } 31 32 33 public ClassDiff(String file1, String file2) throws IOException { 34 this.f1 = ClassFile.parse(file1); 35 this.f2 = ClassFile.parse(file2); 36 } 37 38 public void runDiff() { 39 diff("magic-number", f1.getMagicNumber(), f2.getMagicNumber()); 40 diff("major-version", f1.getMajorVersion(), f2.getMajorVersion()); 41 diff("minor-version", f1.getMinorVersion(), f2.getMinorVersion()); 42 43 45 diff("access-flags", f1.getAccessFlags(), f2.getAccessFlags()); 46 ConstantPool cp1 = f1.getConstantPool(); 47 ConstantPool cp2 = f2.getConstantPool(); 48 49 diffCPEntry("this_class", 50 cp1.get(f1.getThisClassIndex()), 51 cp2.get(f2.getThisClassIndex())); 52 53 diffCPEntry("super_class", 54 cp1.get(f1.getSuperClassIndex()), 55 cp2.get(f2.getSuperClassIndex())); 56 57 diffInterfaces("interface", f1.getInterfaces(), f2.getInterfaces()); 58 diffFields("field", f1.getFields(), f2.getFields()); 59 diffMethods("method", f1.getMethods(), f2.getMethods()); 60 } 61 62 public void diff(String dName, int i1, int i2) { 63 if (i1 != i2) { 64 System.out.println("< " + dName + ": " + i1); 65 System.out.println("> " + dName + ": " + i2); 66 } 67 } 68 69 70 private void diffInstructions(Instruction i1, Instruction i2) { 71 if (i1.getOpcode() != i2.getOpcode()) { 72 System.out.println("< instruction: " + i1); 73 System.out.println("> instruction: " + i2); 74 return; 75 } 76 77 if (i1 instanceof CPInstruction) { 78 CPInstruction cpIns1 = (CPInstruction)i1; 79 CPInstruction cpIns2 = (CPInstruction)i2; 80 81 diffCPEntry("instruction, constant-pool entry", 82 cpIns1.getEntry(), cpIns2.getEntry()); 83 } 84 } 85 86 public void diffCPEntry(String name, ConstantPool.Entry e1, 87 ConstantPool.Entry e2) { 88 if (e1.getClass().getName() != e2.getClass().getName()) { 89 System.out.println("< " + name + ": " + e1); 90 System.out.println("> " + name + ": " + e2); 91 return; 92 } 93 94 if (e1 instanceof ConstantPool.ClassInfo) { 95 ConstantPool.ClassInfo ci1 = (ConstantPool.ClassInfo)e1; 96 ConstantPool.ClassInfo ci2 = (ConstantPool.ClassInfo)e2; 97 String cn1 = ci1.getName(); 98 String cn2 = ci2.getName(); 99 if (!cn1.equals(cn2)) { 100 System.out.println("< " + name + ": " + cn1); 101 System.out.println("> " + name + ": " + cn2); 102 return; 103 } 104 } 105 else if (e1 instanceof ConstantPool.FieldRefInfo) { 106 ConstantPool.FieldRefInfo fri1 = (ConstantPool.FieldRefInfo)e1; 107 ConstantPool.FieldRefInfo fri2 = (ConstantPool.FieldRefInfo)e2; 108 if (!(fri1.getFieldName().equals(fri2.getFieldName()) && 109 fri2.getDescriptor().equals(fri2.getDescriptor()))) { 110 System.out.println("< " + name + ": " + e1); 111 System.out.println("> " + name + ": " + e2); 112 return; 113 } 114 } 115 else if (e1 instanceof ConstantPool.MethodRefInfo) { 116 ConstantPool.MethodRefInfo mri1 = (ConstantPool.MethodRefInfo)e1; 117 ConstantPool.MethodRefInfo mri2 = (ConstantPool.MethodRefInfo)e2; 118 if (!(mri1.getMethodName().equals(mri2.getMethodName()) && 119 mri2.getDescriptor().equals(mri2.getDescriptor()))) { 120 System.out.println("< " + name + ": " + e1); 121 System.out.println("> " + name + ": " + e2); 122 return; 123 } 124 } 125 else if (e1 instanceof ConstantPool.StringInfo) { 126 ConstantPool.StringInfo si1 = (ConstantPool.StringInfo)e1; 127 ConstantPool.StringInfo si2 = (ConstantPool.StringInfo)e2; 128 if (!si1.stringValue().equals(si2.stringValue())) { 129 System.out.println("< " + name + ": " + si1.stringValue()); 130 System.out.println("> " + name + ": " + si2.stringValue()); 131 return; 132 } 133 } 134 else { 135 System.out.println("ERROR: comparison not defined: " + e1 + ", " + 136 e2); 137 } 138 } 139 140 141 private void diffInterfaces(String name, List il1, List il2) { 142 Iterator i1 = il1.iterator(); 143 Iterator i2 = il2.iterator(); 144 145 Interface if1 = null; 146 Interface if2 = null; 147 while(i1.hasNext()) { 148 if1 = (Interface)i1.next(); 149 String n1 = if1.getName(); 150 String n2 = null; 151 if (i2.hasNext()) { 152 if2 = (Interface)i2.next(); 153 n2 = if2.getName(); 154 } 155 156 if (n2 != null) { 157 if (!(n1.equals(n2))) { 158 System.out.println("< " + name + ": " + n1); 159 System.out.println("> " + name + ": " + n2); 160 } 161 } 162 else { 163 System.out.println("< only here, " + name + ": " + n1); 164 } 165 } 166 167 while(i2.hasNext()) { 168 if2 = (Interface)i2.next(); 169 System.out.println("> only here, " + name + ": " + if2.getName()); 170 } 171 } 172 173 174 private void diffFields(String name, List il1, List il2) { 175 Iterator i = il1.iterator(); 176 while(i.hasNext()) { 177 Field f1 = (Field)i.next(); 178 Field f2 = findField(f1.getName(), f1.getDescriptor(), il2); 179 180 if (f2 != null) { 181 if (f1.getAccessFlags() != f2.getAccessFlags()) { 182 System.out.println("< " + name + ": " + 183 Modifier.toString(f1.getAccessFlags()) + 184 " " + f1.getName() + " " + 185 f1.getDescriptor()); 186 System.out.println("> " + name + ": " + 187 Modifier.toString(f2.getAccessFlags()) + 188 " " + f2.getName() + " " + 189 f2.getDescriptor()); 190 } 191 192 diffAttributes("field", f1.getName(), f2.getName(), 193 f1.getAttributes(), f2.getAttributes()); 194 } 195 else { 196 System.out.println("< only here, " + name + ": " + 197 Modifier.toString(f1.getAccessFlags()) +" "+ 198 f1.getName()+ f1.getDescriptor()); 199 } 200 } 201 202 203 i = il2.iterator(); 204 while(i.hasNext()) { 205 Field f1 = (Field)i.next(); 206 Field f2 = findField(f1.getName(), f1.getDescriptor(), il1); 207 208 if (f2 == null) { 209 System.out.println("> only here, " + name + ": " + 210 Modifier.toString(f1.getAccessFlags()) +" "+ 211 f1.getName()+ f1.getDescriptor()); 212 } 213 } 214 } 215 216 217 private void diffMethods(String name, List il1, List il2) { 218 Iterator i = il1.iterator(); 219 while(i.hasNext()) { 220 Method m1 = (Method)i.next(); 221 Method m2 = findMethod(m1.getName(), m1.getDescriptor(), il2); 222 223 if (m2 != null) { 224 if (m1.getAccessFlags() != m2.getAccessFlags()) { 225 System.out.println("< " + name + ": " + 226 Modifier.toString(m1.getAccessFlags()) + 227 " " + m1.getName() +m1.getDescriptor()); 228 System.out.println("> " + name + ": " + 229 Modifier.toString(m2.getAccessFlags()) + 230 " " + m2.getName() +m2.getDescriptor()); 231 } 232 233 diffAttributes("method", m1.getName(), m2.getName(), 234 m1.getAttributes(), m2.getAttributes()); 235 } 236 else { 237 System.out.println("< only here, " + name + ": " + 238 Modifier.toString(m1.getAccessFlags()) +" "+ 239 m1.getName()+ m1.getDescriptor()); 240 } 241 242 JiapiMethod jm1 = new JiapiMethod(m1); 243 JiapiMethod jm2 = new JiapiMethod(m2); 244 diffInstructions(jm1, jm2); 245 } 246 247 248 i = il2.iterator(); 249 while(i.hasNext()) { 250 Method m1 = (Method)i.next(); 251 Method m2 = findMethod(m1.getName(), m1.getDescriptor(), il1); 252 253 if (m2 == null) { 254 System.out.println("> only here, " + name + ": " + 255 Modifier.toString(m1.getAccessFlags()) +" "+ 256 m1.getName()+ m1.getDescriptor()); 257 } 258 } 259 } 260 261 262 263 private void diffAttributes(String name, String n1, String n2, 264 List al1, List al2) { 265 Iterator i = al1.iterator(); 266 while(i.hasNext()) { 267 Attribute a1 = (Attribute)i.next(); 268 Attribute a2 = findAttribute(a1.getName(), al2); 269 270 if (a2 != null) { 271 if (a1 instanceof CodeAttribute) { 272 diffCodeAttributes((CodeAttribute)a1, (CodeAttribute)a2); 273 } 274 else if (a1 instanceof LineNumberTableAttribute) { 275 diffLNTableAttributes((LineNumberTableAttribute)a1, 276 (LineNumberTableAttribute)a2); 277 } 278 else if (a1 instanceof LocalVariableTableAttribute) { 279 diffLVTableAttributes((LocalVariableTableAttribute)a1, 280 (LocalVariableTableAttribute)a2); 281 } 282 else { 283 System.out.println("diff: " + a1.getName() + 284 " not implemented"); 285 } 286 } 287 else { 288 System.out.println("< only here, " + name + "(" + n1 + 289 ") attribute: '" + a1.getName() + "'"); 290 if (a1 instanceof LocalVariableTableAttribute) { 291 printLVTable((LocalVariableTableAttribute)a1); 292 } 293 } 294 } 295 296 297 i = al2.iterator(); 298 while(i.hasNext()) { 299 Attribute a1 = (Attribute)i.next(); 300 Attribute a2 = findAttribute(a1.getName(), al1); 301 302 if (a2 == null) { 303 System.out.println("> only here, " + name + "(" + n2 + 304 ") attribute: '" + a1.getName() + "'"); 305 if (a1 instanceof LocalVariableTableAttribute) { 306 printLVTable((LocalVariableTableAttribute)a1); 307 } 308 } 309 } 310 } 311 312 private void diffInstructions(JiapiMethod jm1, JiapiMethod jm2){ 313 InstructionList il1 = jm1.getInstructionList(); 314 InstructionList il2 = jm2.getInstructionList(); 315 316 diff("instruction-list size", il1.size(), il2.size()); 317 318 for (int i = 0; (i < il1.size()) && (i < il2.size()); i++) { 319 diffInstructions(il1.get(i), il2.get(i)); 320 } 321 } 322 323 324 private void diffCodeAttributes(CodeAttribute a1, CodeAttribute a2) { 325 diff("max-locals", a1.getMaxLocals(), a2.getMaxLocals()); 326 diff("max-stack", a1.getMaxStack(), a2.getMaxStack()); 327 328 diffAttributes("attribute", "c1", "c2", 329 a1.getAttributes(), a2.getAttributes()); 330 } 331 332 private void diffLNTableAttributes(LineNumberTableAttribute a1, 333 LineNumberTableAttribute a2) { 334 } 335 336 private void diffLVTableAttributes(LocalVariableTableAttribute a1, 337 LocalVariableTableAttribute a2) { 338 } 339 340 341 private Method findMethod(String name, String descriptor, List il) { 342 Iterator i = il.iterator(); 343 while(i.hasNext()) { 344 Method m = (Method)i.next(); 345 if (name.equals(m.getName()) && 346 descriptor.equals(m.getDescriptor())) { 347 return m; 348 } 349 } 350 351 return null; 352 } 353 354 private Field findField(String name, String descriptor, List il) { 355 Iterator i = il.iterator(); 356 while(i.hasNext()) { 357 Field f = (Field)i.next(); 358 if (name.equals(f.getName()) && 359 descriptor.equals(f.getDescriptor())) { 360 return f; 361 } 362 } 363 364 return null; 365 } 366 367 private Attribute findAttribute(String name, List il) { 368 Iterator i = il.iterator(); 369 while(i.hasNext()) { 370 Attribute a = (Attribute)i.next(); 371 if (name.equals(a.getName())) { 372 return a; 373 } 374 } 375 376 return null; 377 } 378 379 private void printLVTable(LocalVariableTableAttribute lvta) { 380 List lvt = lvta.getLocalVariables(); 381 System.out.println(lvt.size() + " local variables"); 382 Iterator i = lvt.iterator(); 383 System.out.println(" start_pc length name descriptor index"); 384 while(i.hasNext()) { 385 LocalVariableTableAttribute.LocalVariable lv = 386 (LocalVariableTableAttribute.LocalVariable)i.next(); 387 388 System.out.println(" " + lv.getStartPc() + " " + lv.getLength() + 389 " " + lv.getName() + " " + lv.getDescriptor() + 390 " " + lv.getIndex()); 391 } 392 } 393 } 394 | Popular Tags |