1 /******************************************************************************* 2 * Copyright (c) 2000, 2020 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for 14 * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) 15 * Jesper Steen Moeller - Contributions for: 16 * Bug 406973 - [compiler] Parse MethodParameters attribute 17 *******************************************************************************/ 18 package org.eclipse.jdt.internal.core.util; 19 20 import org.eclipse.jdt.core.JavaCore; 21 import org.eclipse.jdt.core.Signature; 22 import org.eclipse.jdt.core.compiler.CharOperation; 23 import org.eclipse.jdt.core.util.*; 24 import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; 25 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; 26 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; 27 28 /** 29 * Disassembler of .class files. It generates an output in the Writer that looks close to 30 * the javap output. 31 */ 32 public class Disassembler extends ClassFileBytesDisassembler { 33 34 private static final char[] ANY_EXCEPTION = Messages.classfileformat_anyexceptionhandler.toCharArray(); 35 private static final String VERSION_UNKNOWN = Messages.classfileformat_versionUnknown; 36 appendModifier(StringBuffer buffer, int accessFlags, int modifierConstant, String modifier, boolean firstModifier)37 private boolean appendModifier(StringBuffer buffer, int accessFlags, int modifierConstant, String modifier, boolean firstModifier) { 38 if ((accessFlags & modifierConstant) != 0) { 39 if (!firstModifier) { 40 buffer.append(Messages.disassembler_space); 41 } 42 if (firstModifier) { 43 firstModifier = false; 44 } 45 buffer.append(modifier); 46 } 47 return firstModifier; 48 } 49 decodeModifiers(StringBuffer buffer, int accessFlags, int[] checkBits)50 private void decodeModifiers(StringBuffer buffer, int accessFlags, int[] checkBits) { 51 decodeModifiers(buffer, accessFlags, false, false, checkBits); 52 } 53 decodeModifiers(StringBuffer buffer, int accessFlags, boolean printDefault, boolean asBridge, int[] checkBits)54 private void decodeModifiers(StringBuffer buffer, int accessFlags, boolean printDefault, boolean asBridge, int[] checkBits) { 55 if (checkBits == null) return; 56 boolean firstModifier = true; 57 for (int i = 0, max = checkBits.length; i < max; i++) { 58 switch(checkBits[i]) { 59 case IModifierConstants.ACC_PUBLIC : 60 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PUBLIC, "public", firstModifier); //$NON-NLS-1$ 61 break; 62 case IModifierConstants.ACC_PROTECTED : 63 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PROTECTED, "protected", firstModifier); //$NON-NLS-1$ 64 break; 65 case IModifierConstants.ACC_PRIVATE : 66 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PRIVATE, "private", firstModifier); //$NON-NLS-1$ 67 break; 68 case IModifierConstants.ACC_ABSTRACT : 69 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ABSTRACT, "abstract", firstModifier); //$NON-NLS-1$ 70 break; 71 case IModifierConstants.ACC_STATIC : 72 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STATIC, "static", firstModifier); //$NON-NLS-1$ 73 break; 74 case IModifierConstants.ACC_FINAL : 75 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_FINAL, "final", firstModifier); //$NON-NLS-1$ 76 break; 77 case IModifierConstants.ACC_SYNCHRONIZED : 78 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_SYNCHRONIZED, "synchronized", firstModifier); //$NON-NLS-1$ 79 break; 80 case IModifierConstants.ACC_NATIVE : 81 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_NATIVE, "native", firstModifier); //$NON-NLS-1$ 82 break; 83 case IModifierConstants.ACC_STRICT : 84 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STRICT, "strictfp", firstModifier); //$NON-NLS-1$ 85 break; 86 case IModifierConstants.ACC_TRANSIENT : 87 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_TRANSIENT, "transient", firstModifier); //$NON-NLS-1$ 88 break; 89 case IModifierConstants.ACC_VOLATILE : 90 // case IModifierConstants.ACC_BRIDGE : 91 if (asBridge) { 92 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_BRIDGE, "bridge", firstModifier); //$NON-NLS-1$ 93 } else { 94 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_VOLATILE, "volatile", firstModifier); //$NON-NLS-1$ 95 } 96 break; 97 case IModifierConstants.ACC_ENUM : 98 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ENUM, "enum", firstModifier); //$NON-NLS-1$ 99 break; 100 case IModifierConstants.ACC_SYNTHETIC : 101 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_SYNTHETIC, "synthetic", firstModifier); //$NON-NLS-1$ 102 break; 103 case IModifierConstants.ACC_MANDATED : 104 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_MANDATED, "mandated", firstModifier); //$NON-NLS-1$ 105 break; 106 } 107 } 108 if (!firstModifier) { 109 if (!printDefault) buffer.append(Messages.disassembler_space); 110 } else if (printDefault) { 111 // no modifier: package default visibility 112 buffer.append("default"); //$NON-NLS-1$ 113 } 114 } 115 decodeModifiersForField(StringBuffer buffer, int accessFlags)116 private void decodeModifiersForField(StringBuffer buffer, int accessFlags) { 117 decodeModifiers(buffer, accessFlags, new int[] { 118 IModifierConstants.ACC_PUBLIC, 119 IModifierConstants.ACC_PROTECTED, 120 IModifierConstants.ACC_PRIVATE, 121 IModifierConstants.ACC_STATIC, 122 IModifierConstants.ACC_FINAL, 123 IModifierConstants.ACC_TRANSIENT, 124 IModifierConstants.ACC_VOLATILE, 125 IModifierConstants.ACC_ENUM 126 }); 127 } 128 decodeModifiersForFieldForWorkingCopy(StringBuffer buffer, int accessFlags)129 private void decodeModifiersForFieldForWorkingCopy(StringBuffer buffer, int accessFlags) { 130 decodeModifiers(buffer, accessFlags, new int[] { 131 IModifierConstants.ACC_PUBLIC, 132 IModifierConstants.ACC_PROTECTED, 133 IModifierConstants.ACC_PRIVATE, 134 IModifierConstants.ACC_STATIC, 135 IModifierConstants.ACC_FINAL, 136 IModifierConstants.ACC_TRANSIENT, 137 IModifierConstants.ACC_VOLATILE, 138 }); 139 } 140 decodeModifiersForInnerClasses(StringBuffer buffer, int accessFlags, boolean printDefault)141 private final void decodeModifiersForInnerClasses(StringBuffer buffer, int accessFlags, boolean printDefault) { 142 decodeModifiers(buffer, accessFlags, printDefault, false, new int[] { 143 IModifierConstants.ACC_PUBLIC, 144 IModifierConstants.ACC_PROTECTED, 145 IModifierConstants.ACC_PRIVATE, 146 IModifierConstants.ACC_ABSTRACT, 147 IModifierConstants.ACC_STATIC, 148 IModifierConstants.ACC_FINAL, 149 }); 150 } 151 decodeModifiersForMethod(StringBuffer buffer, int accessFlags)152 private final void decodeModifiersForMethod(StringBuffer buffer, int accessFlags) { 153 decodeModifiers(buffer, accessFlags, false, true, new int[] { 154 IModifierConstants.ACC_PUBLIC, 155 IModifierConstants.ACC_PROTECTED, 156 IModifierConstants.ACC_PRIVATE, 157 IModifierConstants.ACC_ABSTRACT, 158 IModifierConstants.ACC_STATIC, 159 IModifierConstants.ACC_FINAL, 160 IModifierConstants.ACC_SYNCHRONIZED, 161 IModifierConstants.ACC_NATIVE, 162 IModifierConstants.ACC_STRICT, 163 IModifierConstants.ACC_BRIDGE, 164 }); 165 } 166 decodeModifiersForMethodParameters(StringBuffer buffer, int accessFlags)167 private final void decodeModifiersForMethodParameters(StringBuffer buffer, int accessFlags) { 168 decodeModifiers(buffer, accessFlags, false, true, new int[] { 169 IModifierConstants.ACC_FINAL, 170 IModifierConstants.ACC_MANDATED, 171 IModifierConstants.ACC_SYNTHETIC, 172 }); 173 } 174 decodeModifiersForType(StringBuffer buffer, int accessFlags)175 private final void decodeModifiersForType(StringBuffer buffer, int accessFlags) { 176 decodeModifiers(buffer, accessFlags, new int[] { 177 IModifierConstants.ACC_PUBLIC, 178 IModifierConstants.ACC_ABSTRACT, 179 IModifierConstants.ACC_FINAL, 180 }); 181 } decodeModifiersForModuleRequires(StringBuffer buffer, int accessFlags)182 private final void decodeModifiersForModuleRequires(StringBuffer buffer, int accessFlags) { 183 int[] checkBits = new int[] { 184 IModifierConstants.ACC_TRANSITIVE, 185 IModifierConstants.ACC_STATIC_PHASE, 186 }; 187 boolean firstModifier = true; 188 for (int i = 0, max = checkBits.length; i < max; i++) { 189 switch(checkBits[i]) { 190 case IModifierConstants.ACC_TRANSITIVE : 191 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_TRANSITIVE, "transitive", firstModifier); //$NON-NLS-1$ 192 break; 193 case IModifierConstants.ACC_STATIC_PHASE : 194 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STATIC_PHASE, "protected", firstModifier); //$NON-NLS-1$ 195 break; 196 } 197 } 198 if (!firstModifier) { 199 buffer.append(Messages.disassembler_space); 200 } 201 } decodeModifiersForModule(StringBuffer buffer, int accessFlags)202 private final void decodeModifiersForModule(StringBuffer buffer, int accessFlags) { 203 appendModifier(buffer, accessFlags, IModifierConstants.ACC_OPEN, "open", true); //$NON-NLS-1$ 204 buffer.append(Messages.disassembler_space); 205 } escapeString(String s)206 public static String escapeString(String s) { 207 return decodeStringValue(s); 208 } 209 decodeStringValue(char[] chars)210 static String decodeStringValue(char[] chars) { 211 StringBuffer buffer = new StringBuffer(); 212 for (int i = 0, max = chars.length; i < max; i++) { 213 char c = chars[i]; 214 org.eclipse.jdt.internal.compiler.util.Util.appendEscapedChar(buffer, c, true); 215 } 216 return buffer.toString(); 217 } 218 escapeChar(StringBuffer buffer, char c)219 private static void escapeChar(StringBuffer buffer, char c) { 220 org.eclipse.jdt.internal.compiler.util.Util.appendEscapedChar(buffer, c, false); 221 } 222 decodeStringValue(String s)223 static String decodeStringValue(String s) { 224 return decodeStringValue(s.toCharArray()); 225 } 226 227 /** 228 * @see org.eclipse.jdt.core.util.ClassFileBytesDisassembler#disassemble(byte[], java.lang.String) 229 */ 230 @Override disassemble(byte[] classFileBytes, String lineSeparator)231 public String disassemble(byte[] classFileBytes, String lineSeparator) throws ClassFormatException { 232 try { 233 return disassemble(new ClassFileReader(classFileBytes, IClassFileReader.ALL), lineSeparator, ClassFileBytesDisassembler.DEFAULT); 234 } catch (ArrayIndexOutOfBoundsException e) { 235 throw new ClassFormatException(e.getMessage(), e); 236 } 237 } 238 239 /** 240 * @see org.eclipse.jdt.core.util.ClassFileBytesDisassembler#disassemble(byte[], java.lang.String, int) 241 */ 242 @Override disassemble(byte[] classFileBytes, String lineSeparator, int mode)243 public String disassemble(byte[] classFileBytes, String lineSeparator, int mode) throws ClassFormatException { 244 try { 245 return disassemble(new ClassFileReader(classFileBytes, IClassFileReader.ALL), lineSeparator, mode); 246 } catch (ArrayIndexOutOfBoundsException e) { 247 throw new ClassFormatException(e.getMessage(), e); 248 } 249 } 250 disassemble(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)251 private void disassemble(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 252 writeNewLine(buffer, lineSeparator, tabNumber + 1); 253 final int typeIndex = annotation.getTypeIndex(); 254 final char[] typeName = CharOperation.replaceOnCopy(annotation.getTypeName(), '/', '.'); 255 buffer.append( 256 Messages.bind(Messages.disassembler_annotationentrystart, new String[] { 257 Integer.toString(typeIndex), 258 new String(returnClassName(Signature.toCharArray(typeName), '.', mode)) 259 })); 260 final IAnnotationComponent[] components = annotation.getComponents(); 261 for (int i = 0, max = components.length; i < max; i++) { 262 disassemble(components[i], buffer, lineSeparator, tabNumber + 1, mode); 263 } 264 writeNewLine(buffer, lineSeparator, tabNumber + 1); 265 buffer.append(Messages.disassembler_annotationentryend); 266 } 267 disassemble(IExtendedAnnotation extendedAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)268 private void disassemble(IExtendedAnnotation extendedAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 269 writeNewLine(buffer, lineSeparator, tabNumber + 1); 270 final int typeIndex = extendedAnnotation.getTypeIndex(); 271 final char[] typeName = CharOperation.replaceOnCopy(extendedAnnotation.getTypeName(), '/', '.'); 272 buffer.append( 273 Messages.bind(Messages.disassembler_extendedannotationentrystart, new String[] { 274 Integer.toString(typeIndex), 275 new String(returnClassName(Signature.toCharArray(typeName), '.', mode)) 276 })); 277 final IAnnotationComponent[] components = extendedAnnotation.getComponents(); 278 for (int i = 0, max = components.length; i < max; i++) { 279 disassemble(components[i], buffer, lineSeparator, tabNumber + 1, mode); 280 } 281 writeNewLine(buffer, lineSeparator, tabNumber + 2); 282 int targetType = extendedAnnotation.getTargetType(); 283 buffer.append( 284 Messages.bind(Messages.disassembler_extendedannotation_targetType, new String[] { 285 Integer.toHexString(targetType), 286 getTargetType(targetType), 287 })); 288 switch(targetType) { 289 case IExtendedAnnotationConstants.METHOD_RECEIVER : 290 case IExtendedAnnotationConstants.METHOD_RETURN: 291 case IExtendedAnnotationConstants.FIELD : 292 break; 293 default: 294 writeNewLine(buffer, lineSeparator, tabNumber + 2); 295 disassembleTargetTypeContents(false, targetType, extendedAnnotation, buffer, lineSeparator, tabNumber, mode); 296 } 297 disassembleTypePathContents(targetType, extendedAnnotation, buffer, lineSeparator, tabNumber, mode); 298 writeNewLine(buffer, lineSeparator, tabNumber + 1); 299 buffer.append(Messages.disassembler_extendedannotationentryend); 300 } 301 disassembleTypePathContents(int targetType, IExtendedAnnotation extendedAnnotation,StringBuffer buffer, String lineSeparator, int tabNumber, int mode)302 private void disassembleTypePathContents(int targetType, IExtendedAnnotation extendedAnnotation,StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 303 int[][] typepath = extendedAnnotation.getTypePath(); 304 if (typepath.length != 0) { 305 writeNewLine(buffer, lineSeparator, tabNumber + 2); 306 buffer.append( 307 Messages.bind(Messages.disassembler_extendedannotation_typepath, new String[] { 308 toTypePathString(typepath), 309 })); 310 } 311 } disassembleTargetTypeContents(boolean insideWildcard, int targetType, IExtendedAnnotation extendedAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)312 private void disassembleTargetTypeContents(boolean insideWildcard, int targetType, IExtendedAnnotation extendedAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 313 switch(targetType) { 314 case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER : 315 case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER : 316 buffer.append( 317 Messages.bind(Messages.disassembler_extendedannotation_type_parameter, new String[] { 318 Integer.toString(extendedAnnotation.getTypeParameterIndex()), 319 })); 320 break; 321 case IExtendedAnnotationConstants.CLASS_EXTENDS : 322 buffer.append( 323 Messages.bind(Messages.disassembler_extendedannotation_classextendsimplements, new String[] { 324 Integer.toString(extendedAnnotation.getAnnotationTypeIndex()), 325 })); 326 break; 327 328 case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER_BOUND : 329 case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_BOUND : 330 buffer.append( 331 Messages.bind(Messages.disassembler_extendedannotation_type_parameter_with_bound, new String[] { 332 Integer.toString(extendedAnnotation.getTypeParameterIndex()), 333 Integer.toString(extendedAnnotation.getTypeParameterBoundIndex()), 334 })); 335 break; 336 case IExtendedAnnotationConstants.FIELD : 337 case IExtendedAnnotationConstants.METHOD_RETURN : 338 case IExtendedAnnotationConstants.METHOD_RECEIVER : 339 break; 340 case IExtendedAnnotationConstants.METHOD_FORMAL_PARAMETER : 341 buffer.append( 342 Messages.bind(Messages.disassembler_extendedannotation_method_parameter, new String[] { 343 Integer.toString(extendedAnnotation.getParameterIndex()), 344 })); 345 break; 346 case IExtendedAnnotationConstants.THROWS : 347 buffer.append( 348 Messages.bind(Messages.disassembler_extendedannotation_throws, new String[] { 349 Integer.toString(extendedAnnotation.getAnnotationTypeIndex()), 350 })); 351 break; 352 353 case IExtendedAnnotationConstants.LOCAL_VARIABLE : 354 case IExtendedAnnotationConstants.RESOURCE_VARIABLE : 355 buffer.append(Messages.disassembler_localvariabletargetheader); 356 writeNewLine(buffer, lineSeparator, tabNumber + 3); 357 int localVariableTableSize = extendedAnnotation.getLocalVariableRefenceInfoLength(); 358 ILocalVariableReferenceInfo[] localVariableTable = extendedAnnotation.getLocalVariableTable(); 359 for (int i = 0; i < localVariableTableSize; i++) { 360 if (i != 0) { 361 writeNewLine(buffer, lineSeparator, tabNumber + 3); 362 } 363 ILocalVariableReferenceInfo info = localVariableTable[i]; 364 int index= info.getIndex(); 365 int startPC = info.getStartPC(); 366 int length = info.getLength(); 367 buffer.append(Messages.bind(Messages.classfileformat_localvariablereferenceinfoentry, 368 new String[] { 369 Integer.toString(startPC), 370 Integer.toString(startPC + length), 371 Integer.toString(index), 372 })); 373 } 374 break; 375 case IExtendedAnnotationConstants.EXCEPTION_PARAMETER : 376 buffer.append( 377 Messages.bind(Messages.disassembler_extendedannotation_exception_table_index, new String[] { 378 Integer.toString(extendedAnnotation.getExceptionTableIndex()), 379 })); 380 break; 381 382 case IExtendedAnnotationConstants.INSTANCEOF : 383 case IExtendedAnnotationConstants.NEW : 384 case IExtendedAnnotationConstants.CONSTRUCTOR_REFERENCE : 385 case IExtendedAnnotationConstants.METHOD_REFERENCE : 386 buffer.append( 387 Messages.bind(Messages.disassembler_extendedannotation_offset, new String[] { 388 Integer.toString(extendedAnnotation.getOffset()), 389 })); 390 break; 391 case IExtendedAnnotationConstants.CAST : 392 case IExtendedAnnotationConstants.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT : 393 case IExtendedAnnotationConstants.METHOD_INVOCATION_TYPE_ARGUMENT : 394 case IExtendedAnnotationConstants.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT : 395 case IExtendedAnnotationConstants.METHOD_REFERENCE_TYPE_ARGUMENT : 396 buffer.append( 397 Messages.bind(Messages.disassembler_extendedannotation_offset, new String[] { 398 Integer.toString(extendedAnnotation.getOffset()), 399 })); 400 writeNewLine(buffer, lineSeparator, tabNumber + 2); 401 buffer.append( 402 Messages.bind(Messages.disassembler_extendedannotation_type_argument, new String[] { 403 Integer.toString(extendedAnnotation.getAnnotationTypeIndex()), 404 })); 405 break; 406 } 407 } getTargetType(int targetType)408 private String getTargetType(int targetType) { 409 switch(targetType) { 410 case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER : 411 return "CLASS_TYPE_PARAMETER"; //$NON-NLS-1$ 412 case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER : 413 return "METHOD_TYPE_PARAMETER"; //$NON-NLS-1$ 414 415 case IExtendedAnnotationConstants.CLASS_EXTENDS : 416 return "CLASS_EXTENDS"; //$NON-NLS-1$ 417 case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER_BOUND : 418 return "CLASS_TYPE_PARAMETER_BOUND"; //$NON-NLS-1$ 419 case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_BOUND : 420 return "METHOD_TYPE_PARAMETER_BOUND"; //$NON-NLS-1$ 421 case IExtendedAnnotationConstants.FIELD : 422 return "FIELD"; //$NON-NLS-1$ 423 case IExtendedAnnotationConstants.METHOD_RETURN : 424 return "METHOD_RETURN"; //$NON-NLS-1$ 425 case IExtendedAnnotationConstants.METHOD_RECEIVER : 426 return "METHOD_RECEIVER"; //$NON-NLS-1$ 427 case IExtendedAnnotationConstants.METHOD_FORMAL_PARAMETER : 428 return "METHOD_FORMAL_PARAMETER"; //$NON-NLS-1$ 429 case IExtendedAnnotationConstants.THROWS : 430 return "THROWS"; //$NON-NLS-1$ 431 432 case IExtendedAnnotationConstants.LOCAL_VARIABLE : 433 return "LOCAL_VARIABLE"; //$NON-NLS-1$ 434 case IExtendedAnnotationConstants.RESOURCE_VARIABLE : 435 return "RESOURCE_VARIABLE"; //$NON-NLS-1$ 436 case IExtendedAnnotationConstants.EXCEPTION_PARAMETER : 437 return "EXCEPTION_PARAMETER"; //$NON-NLS-1$ 438 case IExtendedAnnotationConstants.INSTANCEOF : 439 return "INSTANCEOF"; //$NON-NLS-1$ 440 case IExtendedAnnotationConstants.NEW : 441 return "NEW"; //$NON-NLS-1$ 442 case IExtendedAnnotationConstants.CONSTRUCTOR_REFERENCE : 443 return "CONSTRUCTOR_REFERENCE"; //$NON-NLS-1$ 444 case IExtendedAnnotationConstants.METHOD_REFERENCE : 445 return "METHOD_REFERENCE"; //$NON-NLS-1$ 446 case IExtendedAnnotationConstants.CAST : 447 return "CAST"; //$NON-NLS-1$ 448 case IExtendedAnnotationConstants.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT : 449 return "CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT"; //$NON-NLS-1$ 450 case IExtendedAnnotationConstants.METHOD_INVOCATION_TYPE_ARGUMENT : 451 return "METHOD_INVOCATION_TYPE_ARGUMENT"; //$NON-NLS-1$ 452 case IExtendedAnnotationConstants.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT : 453 return "CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT"; //$NON-NLS-1$ 454 case IExtendedAnnotationConstants.METHOD_REFERENCE_TYPE_ARGUMENT : 455 return "METHOD_REFERENCE_TYPE_ARGUMENT"; //$NON-NLS-1$ 456 default: 457 return "UNKNOWN"; //$NON-NLS-1$ 458 } 459 } 460 461 disassemble(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)462 private void disassemble(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 463 writeNewLine(buffer, lineSeparator, tabNumber + 1); 464 buffer.append( 465 Messages.bind(Messages.disassembler_annotationcomponent, 466 new String[] { 467 Integer.toString(annotationComponent.getComponentNameIndex()), 468 new String(annotationComponent.getComponentName()) 469 })); 470 disassemble(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1, mode); 471 } 472 disassemble(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)473 private void disassemble(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 474 switch(annotationComponentValue.getTag()) { 475 case IAnnotationComponentValue.BYTE_TAG: 476 case IAnnotationComponentValue.CHAR_TAG: 477 case IAnnotationComponentValue.DOUBLE_TAG: 478 case IAnnotationComponentValue.FLOAT_TAG: 479 case IAnnotationComponentValue.INTEGER_TAG: 480 case IAnnotationComponentValue.LONG_TAG: 481 case IAnnotationComponentValue.SHORT_TAG: 482 case IAnnotationComponentValue.BOOLEAN_TAG: 483 case IAnnotationComponentValue.STRING_TAG: 484 IConstantPoolEntry constantPoolEntry = annotationComponentValue.getConstantValue(); 485 String value = null; 486 switch(constantPoolEntry.getKind()) { 487 case IConstantPoolConstant.CONSTANT_Long : 488 value = constantPoolEntry.getLongValue() + "L"; //$NON-NLS-1$ 489 break; 490 case IConstantPoolConstant.CONSTANT_Float : 491 value = constantPoolEntry.getFloatValue() + "f"; //$NON-NLS-1$ 492 break; 493 case IConstantPoolConstant.CONSTANT_Double : 494 value = Double.toString(constantPoolEntry.getDoubleValue()); 495 break; 496 case IConstantPoolConstant.CONSTANT_Integer: 497 StringBuffer temp = new StringBuffer(); 498 switch(annotationComponentValue.getTag()) { 499 case IAnnotationComponentValue.CHAR_TAG : 500 temp.append('\''); 501 escapeChar(temp, (char) constantPoolEntry.getIntegerValue()); 502 temp.append('\''); 503 break; 504 case IAnnotationComponentValue.BOOLEAN_TAG : 505 temp.append(constantPoolEntry.getIntegerValue() == 1 ? "true" : "false");//$NON-NLS-1$//$NON-NLS-2$ 506 break; 507 case IAnnotationComponentValue.BYTE_TAG : 508 temp.append("(byte) ").append(constantPoolEntry.getIntegerValue()); //$NON-NLS-1$ 509 break; 510 case IAnnotationComponentValue.SHORT_TAG : 511 temp.append("(short) ").append(constantPoolEntry.getIntegerValue()); //$NON-NLS-1$ 512 break; 513 case IAnnotationComponentValue.INTEGER_TAG : 514 temp.append("(int) ").append(constantPoolEntry.getIntegerValue()); //$NON-NLS-1$ 515 } 516 value = String.valueOf(temp); 517 break; 518 case IConstantPoolConstant.CONSTANT_Utf8: 519 value = "\"" + decodeStringValue(constantPoolEntry.getUtf8Value()) + "\"";//$NON-NLS-1$//$NON-NLS-2$ 520 } 521 buffer.append(Messages.bind(Messages.disassembler_annotationdefaultvalue, value)); 522 break; 523 case IAnnotationComponentValue.ENUM_TAG: 524 final int enumConstantTypeNameIndex = annotationComponentValue.getEnumConstantTypeNameIndex(); 525 final char[] typeName = CharOperation.replaceOnCopy(annotationComponentValue.getEnumConstantTypeName(), '/', '.'); 526 final int enumConstantNameIndex = annotationComponentValue.getEnumConstantNameIndex(); 527 final char[] constantName = annotationComponentValue.getEnumConstantName(); 528 buffer.append(Messages.bind(Messages.disassembler_annotationenumvalue, 529 new String[] { 530 Integer.toString(enumConstantTypeNameIndex), 531 Integer.toString(enumConstantNameIndex), 532 new String(returnClassName(Signature.toCharArray(typeName), '.', mode)), 533 new String(constantName) 534 })); 535 break; 536 case IAnnotationComponentValue.CLASS_TAG: 537 final int classIndex = annotationComponentValue.getClassInfoIndex(); 538 constantPoolEntry = annotationComponentValue.getClassInfo(); 539 final char[] className = CharOperation.replaceOnCopy(constantPoolEntry.getUtf8Value(), '/', '.'); 540 buffer.append(Messages.bind(Messages.disassembler_annotationclassvalue, 541 new String[] { 542 Integer.toString(classIndex), 543 new String(returnClassName(Signature.toCharArray(className), '.', mode)) 544 })); 545 break; 546 case IAnnotationComponentValue.ANNOTATION_TAG: 547 buffer.append(Messages.disassembler_annotationannotationvalue); 548 IAnnotation annotation = annotationComponentValue.getAnnotationValue(); 549 disassemble(annotation, buffer, lineSeparator, tabNumber + 1, mode); 550 break; 551 case IAnnotationComponentValue.ARRAY_TAG: 552 buffer.append(Messages.disassembler_annotationarrayvaluestart); 553 final IAnnotationComponentValue[] annotationComponentValues = annotationComponentValue.getAnnotationComponentValues(); 554 for (int i = 0, max = annotationComponentValues.length; i < max; i++) { 555 writeNewLine(buffer, lineSeparator, tabNumber + 1); 556 disassemble(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1, mode); 557 } 558 writeNewLine(buffer, lineSeparator, tabNumber + 1); 559 buffer.append(Messages.disassembler_annotationarrayvalueend); 560 } 561 } 562 disassemble(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)563 private void disassemble(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 564 writeNewLine(buffer, lineSeparator, tabNumber + 1); 565 buffer.append(Messages.disassembler_annotationdefaultheader); 566 IAnnotationComponentValue componentValue = annotationDefaultAttribute.getMemberValue(); 567 writeNewLine(buffer, lineSeparator, tabNumber + 2); 568 disassemble(componentValue, buffer, lineSeparator, tabNumber + 1, mode); 569 } 570 disassemble(IClassFileAttribute classFileAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)571 private void disassemble(IClassFileAttribute classFileAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 572 writeNewLine(buffer, lineSeparator, tabNumber + 1); 573 buffer.append(Messages.bind(Messages.disassembler_genericattributeheader, 574 new String[] { 575 new String(classFileAttribute.getAttributeName()), 576 Long.toString(classFileAttribute.getAttributeLength()) 577 })); 578 } 579 disassemble(IMethodParametersAttribute methodParametersAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)580 private void disassemble(IMethodParametersAttribute methodParametersAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 581 tabNumber += 2; 582 writeNewLine(buffer, lineSeparator, tabNumber); 583 buffer.append(Messages.disassembler_methodparametersheader); 584 for (int i = 0, length = methodParametersAttribute.getMethodParameterLength(); i < length; ++i) { 585 writeNewLine(buffer, lineSeparator, tabNumber + 1); 586 short accessFlags = methodParametersAttribute.getAccessFlags(i); 587 decodeModifiersForMethodParameters(buffer, accessFlags); 588 char [] parameterName = methodParametersAttribute.getParameterName(i); 589 if (parameterName == null) 590 parameterName = Messages.disassembler_anonymousparametername.toCharArray(); 591 buffer.append(parameterName); 592 } 593 } 594 disassembleEnumConstructor(IClassFileReader classFileReader, char[] className, IMethodInfo methodInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)595 private void disassembleEnumConstructor(IClassFileReader classFileReader, char[] className, IMethodInfo methodInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 596 writeNewLine(buffer, lineSeparator, tabNumber); 597 final ICodeAttribute codeAttribute = methodInfo.getCodeAttribute(); 598 IMethodParametersAttribute methodParametersAttribute = (IMethodParametersAttribute) Util.getAttribute(methodInfo, IAttributeNamesConstants.METHOD_PARAMETERS); 599 char[] methodDescriptor = methodInfo.getDescriptor(); 600 final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS); 601 final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS); 602 // disassemble compact version of annotations 603 if (runtimeInvisibleAnnotationsAttribute != null) { 604 disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 605 writeNewLine(buffer, lineSeparator, tabNumber); 606 } 607 if (runtimeVisibleAnnotationsAttribute != null) { 608 disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 609 writeNewLine(buffer, lineSeparator, tabNumber); 610 } 611 final int accessFlags = methodInfo.getAccessFlags(); 612 decodeModifiersForMethod(buffer, accessFlags & IModifierConstants.ACC_PRIVATE); 613 CharOperation.replace(methodDescriptor, '/', '.'); 614 final boolean isVarArgs = (accessFlags & IModifierConstants.ACC_VARARGS) != 0; 615 final char[] signature = Signature.toCharArray(methodDescriptor, returnClassName(className, '.', COMPACT), getParameterNames(methodDescriptor, codeAttribute, methodParametersAttribute, accessFlags) , !checkMode(mode, COMPACT), false, isVarArgs); 616 int index = CharOperation.indexOf(',', signature); 617 index = CharOperation.indexOf(',', signature, index + 1); 618 buffer.append(signature, 0, CharOperation.indexOf('(', signature) + 1); 619 buffer.append(signature, index + 2, signature.length - index - 2); 620 IExceptionAttribute exceptionAttribute = methodInfo.getExceptionAttribute(); 621 if (exceptionAttribute != null) { 622 buffer.append(" throws "); //$NON-NLS-1$ 623 char[][] exceptionNames = exceptionAttribute.getExceptionNames(); 624 int length = exceptionNames.length; 625 for (int i = 0; i < length; i++) { 626 if (i != 0) { 627 buffer 628 .append(Messages.disassembler_comma) 629 .append(Messages.disassembler_space); 630 } 631 char[] exceptionName = exceptionNames[i]; 632 CharOperation.replace(exceptionName, '/', '.'); 633 buffer.append(returnClassName(exceptionName, '.', mode)); 634 } 635 } 636 if (((accessFlags & IModifierConstants.ACC_NATIVE) == 0) 637 && ((accessFlags & IModifierConstants.ACC_ABSTRACT) == 0)) { 638 buffer.append(" {"); //$NON-NLS-1$ 639 final char[] returnType = Signature.getReturnType(methodDescriptor); 640 if (returnType.length == 1) { 641 switch(returnType[0]) { 642 case 'V' : 643 writeNewLine(buffer, lineSeparator, tabNumber); 644 break; 645 case 'I' : 646 case 'B' : 647 case 'J' : 648 case 'D' : 649 case 'F' : 650 case 'S' : 651 case 'C' : 652 writeNewLine(buffer, lineSeparator, tabNumber + 1); 653 buffer.append("return 0;"); //$NON-NLS-1$ 654 writeNewLine(buffer, lineSeparator, tabNumber); 655 break; 656 default : 657 // boolean 658 writeNewLine(buffer, lineSeparator, tabNumber + 1); 659 buffer.append("return false;"); //$NON-NLS-1$ 660 writeNewLine(buffer, lineSeparator, tabNumber); 661 } 662 } else { 663 // object 664 writeNewLine(buffer, lineSeparator, tabNumber + 1); 665 buffer.append("return null;"); //$NON-NLS-1$ 666 writeNewLine(buffer, lineSeparator, tabNumber); 667 } 668 buffer.append('}'); 669 } else { 670 buffer.append(';'); 671 } 672 } 673 674 /** 675 * Disassemble a method info header 676 */ disassemble(IClassFileReader classFileReader, char[] className, IMethodInfo methodInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)677 private void disassemble(IClassFileReader classFileReader, char[] className, IMethodInfo methodInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 678 writeNewLine(buffer, lineSeparator, tabNumber); 679 final ICodeAttribute codeAttribute = methodInfo.getCodeAttribute(); 680 final char[] methodDescriptor = methodInfo.getDescriptor(); 681 final ISignatureAttribute signatureAttribute = (ISignatureAttribute) Util.getAttribute(methodInfo, IAttributeNamesConstants.SIGNATURE); 682 final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS); 683 final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS); 684 final IClassFileAttribute runtimeVisibleTypeAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS); 685 final IClassFileAttribute runtimeInvisibleTypeAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS); 686 final IClassFileAttribute runtimeVisibleParameterAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS); 687 final IClassFileAttribute runtimeInvisibleParameterAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS); 688 final IClassFileAttribute methodParametersAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.METHOD_PARAMETERS); 689 final IClassFileAttribute annotationDefaultAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.ANNOTATION_DEFAULT); 690 if (checkMode(mode, SYSTEM | DETAILED)) { 691 buffer.append(Messages.bind(Messages.classfileformat_methoddescriptor, 692 new String[] { 693 Integer.toString(methodInfo.getDescriptorIndex()), 694 new String(methodDescriptor) 695 })); 696 if (methodInfo.isDeprecated()) { 697 buffer.append(Messages.disassembler_deprecated); 698 } 699 writeNewLine(buffer, lineSeparator, tabNumber); 700 if (signatureAttribute != null) { 701 buffer.append(Messages.bind(Messages.disassembler_signatureattributeheader, new String(signatureAttribute.getSignature()))); 702 writeNewLine(buffer, lineSeparator, tabNumber); 703 } 704 if (codeAttribute != null) { 705 buffer.append(Messages.bind(Messages.classfileformat_stacksAndLocals, 706 new String[] { 707 Integer.toString(codeAttribute.getMaxStack()), 708 Integer.toString(codeAttribute.getMaxLocals()) 709 })); 710 writeNewLine(buffer, lineSeparator, tabNumber); 711 } 712 } 713 if (checkMode(mode, DETAILED)) { 714 // disassemble compact version of annotations 715 if (runtimeInvisibleAnnotationsAttribute != null) { 716 disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 717 writeNewLine(buffer, lineSeparator, tabNumber); 718 } 719 if (runtimeVisibleAnnotationsAttribute != null) { 720 disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 721 writeNewLine(buffer, lineSeparator, tabNumber); 722 } 723 } 724 final int accessFlags = methodInfo.getAccessFlags(); 725 decodeModifiersForMethod(buffer, accessFlags); 726 if (methodInfo.isSynthetic() && !checkMode(mode, WORKING_COPY)) { 727 buffer.append("synthetic"); //$NON-NLS-1$ 728 buffer.append(Messages.disassembler_space); 729 } 730 CharOperation.replace(methodDescriptor, '/', '.'); 731 final boolean isVarArgs = isVarArgs(methodInfo); 732 char[] methodHeader = null; 733 char[][] parameterNames = null; 734 if (!methodInfo.isClinit()) { 735 parameterNames = getParameterNames(methodDescriptor, codeAttribute, (IMethodParametersAttribute)methodParametersAttribute, accessFlags); 736 } 737 if (methodInfo.isConstructor()) { 738 if (checkMode(mode, WORKING_COPY) && signatureAttribute != null) { 739 final char[] signature = signatureAttribute.getSignature(); 740 CharOperation.replace(signature, '/', '.'); 741 disassembleGenericSignature(mode, buffer, signature); 742 buffer.append(' '); 743 methodHeader = Signature.toCharArray(signature, returnClassName(className, '.', COMPACT), parameterNames, !checkMode(mode, COMPACT), false, isVarArgs); 744 } else { 745 methodHeader = Signature.toCharArray(methodDescriptor, returnClassName(className, '.', COMPACT), parameterNames, !checkMode(mode, COMPACT), false, isVarArgs); 746 } 747 } else if (methodInfo.isClinit()) { 748 methodHeader = Messages.bind(Messages.classfileformat_clinitname).toCharArray(); 749 } else { 750 if (checkMode(mode, WORKING_COPY) && signatureAttribute != null) { 751 final char[] signature = signatureAttribute.getSignature(); 752 CharOperation.replace(signature, '/', '.'); 753 disassembleGenericSignature(mode, buffer, signature); 754 buffer.append(' '); 755 methodHeader = Signature.toCharArray(signature, methodInfo.getName(), parameterNames, !checkMode(mode, COMPACT), true, isVarArgs); 756 } else { 757 methodHeader = Signature.toCharArray(methodDescriptor, methodInfo.getName(), parameterNames, !checkMode(mode, COMPACT), true, isVarArgs); 758 } 759 } 760 if (checkMode(mode, DETAILED) && (runtimeInvisibleParameterAnnotationsAttribute != null || runtimeVisibleParameterAnnotationsAttribute != null)) { 761 IParameterAnnotation[] invisibleParameterAnnotations = null; 762 IParameterAnnotation[] visibleParameterAnnotations = null; 763 int length = -1; 764 if (runtimeInvisibleParameterAnnotationsAttribute != null) { 765 IRuntimeInvisibleParameterAnnotationsAttribute attribute = (IRuntimeInvisibleParameterAnnotationsAttribute) runtimeInvisibleParameterAnnotationsAttribute; 766 invisibleParameterAnnotations = attribute.getParameterAnnotations(); 767 length = invisibleParameterAnnotations.length; 768 if (length > 0) { 769 int parameterNamesLength = parameterNames.length; 770 if (length < parameterNamesLength) { 771 System.arraycopy(invisibleParameterAnnotations, 0, (invisibleParameterAnnotations = new IParameterAnnotation[parameterNamesLength]), 1, length); 772 length = parameterNamesLength; 773 } 774 } 775 } 776 if (runtimeVisibleParameterAnnotationsAttribute != null) { 777 IRuntimeVisibleParameterAnnotationsAttribute attribute = (IRuntimeVisibleParameterAnnotationsAttribute) runtimeVisibleParameterAnnotationsAttribute; 778 visibleParameterAnnotations = attribute.getParameterAnnotations(); 779 length = visibleParameterAnnotations.length; 780 if (length > 0) { 781 int parameterNamesLength = parameterNames.length; 782 if (length < parameterNamesLength) { 783 System.arraycopy(visibleParameterAnnotations, 0, (visibleParameterAnnotations = new IParameterAnnotation[parameterNamesLength]), 1, length); 784 length = parameterNamesLength; 785 } 786 } 787 } 788 int insertionPosition = CharOperation.indexOf('(', methodHeader) + 1; 789 int start = 0; 790 StringBuffer stringBuffer = new StringBuffer(); 791 stringBuffer.append(methodHeader, 0, insertionPosition); 792 for (int i = 0; i < length; i++) { 793 if (i > 0) { 794 stringBuffer.append(' '); 795 } 796 int stringBufferSize = stringBuffer.length(); 797 if (visibleParameterAnnotations != null) { 798 disassembleAsModifier(visibleParameterAnnotations, stringBuffer, i, lineSeparator, tabNumber, mode); 799 } 800 if (invisibleParameterAnnotations != null) { 801 if (stringBuffer.length() != stringBufferSize) { 802 stringBuffer.append(' '); 803 stringBufferSize = stringBuffer.length(); 804 } 805 disassembleAsModifier(invisibleParameterAnnotations, stringBuffer, i, lineSeparator, tabNumber, mode); 806 } 807 if (i == 0 && stringBuffer.length() != stringBufferSize) { 808 stringBuffer.append(' '); 809 } 810 start = insertionPosition; 811 insertionPosition = CharOperation.indexOf(',', methodHeader, start + 1) + 1; 812 if (insertionPosition == 0) { 813 stringBuffer.append(methodHeader, start, methodHeader.length - start); 814 } else { 815 stringBuffer.append(methodHeader, start, insertionPosition - start); 816 } 817 } 818 buffer.append(stringBuffer); 819 } else { 820 buffer.append(methodHeader); 821 } 822 IExceptionAttribute exceptionAttribute = methodInfo.getExceptionAttribute(); 823 if (exceptionAttribute != null) { 824 buffer.append(" throws "); //$NON-NLS-1$ 825 char[][] exceptionNames = exceptionAttribute.getExceptionNames(); 826 int length = exceptionNames.length; 827 for (int i = 0; i < length; i++) { 828 if (i != 0) { 829 buffer 830 .append(Messages.disassembler_comma) 831 .append(Messages.disassembler_space); 832 } 833 char[] exceptionName = exceptionNames[i]; 834 CharOperation.replace(exceptionName, '/', '.'); 835 buffer.append(returnClassName(exceptionName, '.', mode)); 836 } 837 } 838 if (checkMode(mode, DETAILED)) { 839 if (annotationDefaultAttribute != null) { 840 buffer.append(" default "); //$NON-NLS-1$ 841 disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode); 842 } 843 } 844 if (checkMode(mode, WORKING_COPY)) { 845 // put the annotation default attribute if needed 846 if (annotationDefaultAttribute != null) { 847 buffer.append(" default "); //$NON-NLS-1$ 848 disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode); 849 } 850 if (((accessFlags & IModifierConstants.ACC_NATIVE) == 0) 851 && ((accessFlags & IModifierConstants.ACC_ABSTRACT) == 0)) { 852 buffer.append(" {"); //$NON-NLS-1$ 853 final char[] returnType = Signature.getReturnType(methodDescriptor); 854 if (returnType.length == 1) { 855 switch(returnType[0]) { 856 case 'V' : 857 writeNewLine(buffer, lineSeparator, tabNumber); 858 break; 859 case 'I' : 860 case 'B' : 861 case 'J' : 862 case 'D' : 863 case 'F' : 864 case 'S' : 865 case 'C' : 866 writeNewLine(buffer, lineSeparator, tabNumber + 1); 867 buffer.append("return 0;"); //$NON-NLS-1$ 868 writeNewLine(buffer, lineSeparator, tabNumber); 869 break; 870 default : 871 // boolean 872 writeNewLine(buffer, lineSeparator, tabNumber + 1); 873 buffer.append("return false;"); //$NON-NLS-1$ 874 writeNewLine(buffer, lineSeparator, tabNumber); 875 } 876 } else { 877 // object 878 writeNewLine(buffer, lineSeparator, tabNumber + 1); 879 buffer.append("return null;"); //$NON-NLS-1$ 880 writeNewLine(buffer, lineSeparator, tabNumber); 881 } 882 buffer.append('}'); 883 } else { 884 buffer.append(';'); 885 } 886 } else { 887 buffer.append(Messages.disassembler_endofmethodheader); 888 } 889 890 if (checkMode(mode, SYSTEM | DETAILED)) { 891 if (codeAttribute != null) { 892 disassemble(codeAttribute, parameterNames, methodDescriptor, (accessFlags & IModifierConstants.ACC_STATIC) != 0, buffer, lineSeparator, tabNumber, mode); 893 } 894 } 895 if (checkMode(mode, SYSTEM | DETAILED)) { 896 if (methodParametersAttribute != null) { 897 disassemble((IMethodParametersAttribute)methodParametersAttribute, buffer, lineSeparator, tabNumber, mode); 898 } 899 } 900 if (checkMode(mode, SYSTEM)) { 901 IClassFileAttribute[] attributes = methodInfo.getAttributes(); 902 int length = attributes.length; 903 if (length != 0) { 904 for (int i = 0; i < length; i++) { 905 IClassFileAttribute attribute = attributes[i]; 906 if (attribute != codeAttribute 907 && attribute != exceptionAttribute 908 && attribute != signatureAttribute 909 && attribute != annotationDefaultAttribute 910 && attribute != runtimeInvisibleAnnotationsAttribute 911 && attribute != runtimeVisibleAnnotationsAttribute 912 && attribute != runtimeInvisibleTypeAnnotationsAttribute 913 && attribute != runtimeVisibleTypeAnnotationsAttribute 914 && attribute != runtimeInvisibleParameterAnnotationsAttribute 915 && attribute != runtimeVisibleParameterAnnotationsAttribute 916 && attribute != methodParametersAttribute 917 && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED) 918 && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) { 919 disassemble(attribute, buffer, lineSeparator, tabNumber, mode); 920 writeNewLine(buffer, lineSeparator, tabNumber); 921 } 922 } 923 } 924 if (annotationDefaultAttribute != null) { 925 disassemble((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode); 926 } 927 if (runtimeVisibleAnnotationsAttribute != null) { 928 disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 929 } 930 if (runtimeInvisibleAnnotationsAttribute != null) { 931 disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 932 } 933 if (runtimeVisibleParameterAnnotationsAttribute != null) { 934 disassemble((IRuntimeVisibleParameterAnnotationsAttribute) runtimeVisibleParameterAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 935 } 936 if (runtimeInvisibleParameterAnnotationsAttribute != null) { 937 disassemble((IRuntimeInvisibleParameterAnnotationsAttribute) runtimeInvisibleParameterAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 938 } 939 if (runtimeVisibleTypeAnnotationsAttribute != null) { 940 disassemble((IRuntimeVisibleTypeAnnotationsAttribute) runtimeVisibleTypeAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 941 } 942 if (runtimeInvisibleTypeAnnotationsAttribute != null) { 943 disassemble((IRuntimeInvisibleTypeAnnotationsAttribute) runtimeInvisibleTypeAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 944 } 945 } 946 } 947 948 /** 949 * @see #disassemble(org.eclipse.jdt.core.util.IClassFileReader, java.lang.String, int) 950 */ disassemble(IClassFileReader classFileReader, String lineSeparator)951 public String disassemble(IClassFileReader classFileReader, String lineSeparator) { 952 return disassemble(classFileReader, lineSeparator, ClassFileBytesDisassembler.DEFAULT); 953 } 954 955 /** 956 * Answers back the disassembled string of the IClassFileReader according to the 957 * mode. 958 * This is an output quite similar to the javap tool. 959 * 960 * @param classFileReader The classFileReader to be disassembled 961 * @param lineSeparator the line separator to use. 962 * @param mode the mode used to disassemble the IClassFileReader 963 * 964 * @return the disassembled string of the IClassFileReader according to the mode 965 */ disassemble(IClassFileReader classFileReader, String lineSeparator, int mode)966 public String disassemble(IClassFileReader classFileReader, String lineSeparator, int mode) { 967 if (classFileReader == null) return org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING; 968 char[] className = classFileReader.getClassName(); 969 if (className == null) { 970 // incomplete initialization. We cannot go further. 971 return org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING; 972 } 973 className= CharOperation.replaceOnCopy(className, '/', '.'); 974 final int classNameLength = className.length; 975 final int accessFlags = classFileReader.getAccessFlags(); 976 final boolean isEnum = (accessFlags & IModifierConstants.ACC_ENUM) != 0; 977 978 StringBuffer buffer = new StringBuffer(); 979 ISourceAttribute sourceAttribute = classFileReader.getSourceFileAttribute(); 980 IClassFileAttribute classFileAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.SIGNATURE); 981 ISignatureAttribute signatureAttribute = (ISignatureAttribute) classFileAttribute; 982 if (checkMode(mode, SYSTEM | DETAILED)) { 983 int minorVersion = classFileReader.getMinorVersion(); 984 int majorVersion = classFileReader.getMajorVersion(); 985 buffer.append(Messages.disassembler_begincommentline); 986 if (sourceAttribute != null) { 987 buffer.append(Messages.disassembler_sourceattributeheader); 988 buffer.append(sourceAttribute.getSourceFileName()); 989 } 990 String versionNumber = VERSION_UNKNOWN; 991 if (minorVersion == 3 && majorVersion == 45) { 992 versionNumber = JavaCore.VERSION_1_1; 993 } else { 994 versionNumber = CompilerOptions.versionFromJdkLevel((majorVersion << 16) + minorVersion); 995 if (versionNumber.length() == 0) 996 versionNumber = VERSION_UNKNOWN; 997 } 998 buffer.append( 999 Messages.bind(Messages.classfileformat_versiondetails, 1000 new String[] { 1001 versionNumber, 1002 Integer.toString(majorVersion), 1003 Integer.toString(minorVersion), 1004 ((accessFlags & IModifierConstants.ACC_SUPER) != 0 1005 ? Messages.classfileformat_superflagisset 1006 : Messages.classfileformat_superflagisnotset) 1007 + (isDeprecated(classFileReader) ? ", deprecated" : org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING)//$NON-NLS-1$ 1008 })); 1009 writeNewLine(buffer, lineSeparator, 0); 1010 if (signatureAttribute != null) { 1011 buffer.append(Messages.bind(Messages.disassembler_signatureattributeheader, new String(signatureAttribute.getSignature()))); 1012 writeNewLine(buffer, lineSeparator, 0); 1013 } 1014 } 1015 final int lastDotIndexInClassName = CharOperation.lastIndexOf('.', className); 1016 1017 if (checkMode(mode, WORKING_COPY) && lastDotIndexInClassName != -1) { 1018 // we print a package declaration 1019 buffer.append("package ");//$NON-NLS-1$ 1020 buffer.append(className, 0, lastDotIndexInClassName); 1021 buffer.append(';'); 1022 writeNewLine(buffer, lineSeparator, 0); 1023 } 1024 1025 INestMembersAttribute nestMembersAttribute = classFileReader.getNestMembersAttribute(); 1026 IInnerClassesAttribute innerClassesAttribute = classFileReader.getInnerClassesAttribute(); 1027 IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS); 1028 IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS); 1029 IClassFileAttribute runtimeVisibleTypeAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS); 1030 IClassFileAttribute runtimeInvisibleTypeAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS); 1031 1032 IClassFileAttribute bootstrapMethods = Util.getAttribute(classFileReader, IAttributeNamesConstants.BOOTSTRAP_METHODS); 1033 IModuleAttribute moduleAttribute = (IModuleAttribute) Util.getAttribute(classFileReader, IAttributeNamesConstants.MODULE); 1034 IRecordAttribute recordAttribute = classFileReader.getRecordAttribute(); 1035 1036 if (checkMode(mode, DETAILED)) { 1037 // disassemble compact version of annotations 1038 if (runtimeInvisibleAnnotationsAttribute != null) { 1039 disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 0, mode); 1040 writeNewLine(buffer, lineSeparator, 0); 1041 } 1042 if (runtimeVisibleAnnotationsAttribute != null) { 1043 disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 0, mode); 1044 writeNewLine(buffer, lineSeparator, 0); 1045 } 1046 } 1047 boolean decoded = false; 1048 if (isEnum && checkMode(mode, WORKING_COPY)) { 1049 decodeModifiersForType(buffer, accessFlags & IModifierConstants.ACC_PUBLIC); 1050 } else { 1051 if (innerClassesAttribute != null) { 1052 // search the right entry 1053 IInnerClassesAttributeEntry[] entries = innerClassesAttribute.getInnerClassAttributesEntries(); 1054 for (int i = 0, max = entries.length; i < max ; i++) { 1055 IInnerClassesAttributeEntry entry = entries[i]; 1056 char[] innerClassName = entry.getInnerClassName(); 1057 if (innerClassName != null) { 1058 if (CharOperation.equals(classFileReader.getClassName(), innerClassName)) { 1059 decodeModifiersForInnerClasses(buffer, entry.getAccessFlags(), false); 1060 decoded = true; 1061 } 1062 } 1063 } 1064 } 1065 if (!decoded) { 1066 decodeModifiersForType(buffer, accessFlags); 1067 if (isSynthetic(classFileReader)) { 1068 buffer.append("synthetic"); //$NON-NLS-1$ 1069 buffer.append(Messages.disassembler_space); 1070 } 1071 } 1072 } 1073 1074 final boolean isAnnotation = (accessFlags & IModifierConstants.ACC_ANNOTATION) != 0; 1075 final boolean isModule = (accessFlags & IModifierConstants.ACC_MODULE) != 0; 1076 boolean isInterface = false; 1077 if (isEnum) { 1078 buffer.append("enum "); //$NON-NLS-1$ 1079 } else if (isModule) { 1080 // skip - process under module attribute 1081 } else if (classFileReader.isClass()) { 1082 if (CharOperation.equals(classFileReader.getSuperclassName(), TypeConstants.CharArray_JAVA_LANG_RECORD_SLASH)) { 1083 buffer.append("record "); //$NON-NLS-1$ 1084 } 1085 else { 1086 buffer.append("class "); //$NON-NLS-1$ 1087 } 1088 } else { 1089 if (isAnnotation) { 1090 buffer.append("@"); //$NON-NLS-1$ 1091 } 1092 buffer.append("interface "); //$NON-NLS-1$ 1093 isInterface = true; 1094 } 1095 1096 if (checkMode(mode, WORKING_COPY)) { 1097 // we print the simple class name 1098 final int start = lastDotIndexInClassName + 1; 1099 buffer.append(className, start, classNameLength - start); 1100 className = CharOperation.subarray(className, start, classNameLength); 1101 if (signatureAttribute != null) { 1102 disassembleGenericSignature(mode, buffer, signatureAttribute.getSignature()); 1103 } 1104 } else if (!isModule) { 1105 buffer.append(className); 1106 } 1107 1108 char[] superclassName = classFileReader.getSuperclassName(); 1109 if (superclassName != null) { 1110 CharOperation.replace(superclassName, '/', '.'); 1111 if (!isJavaLangObject(superclassName) && !isEnum) { 1112 buffer.append(" extends "); //$NON-NLS-1$ 1113 buffer.append(returnClassName(superclassName, '.', mode)); 1114 } 1115 } 1116 if (!isAnnotation || !checkMode(mode, WORKING_COPY)) { 1117 char[][] superclassInterfaces = classFileReader.getInterfaceNames(); 1118 int length = superclassInterfaces.length; 1119 if (length != 0) { 1120 if (isInterface) { 1121 buffer.append(" extends "); //$NON-NLS-1$ 1122 } else { 1123 buffer.append(" implements "); //$NON-NLS-1$ 1124 } 1125 for (int i = 0; i < length; i++) { 1126 if (i != 0) { 1127 buffer 1128 .append(Messages.disassembler_comma) 1129 .append(Messages.disassembler_space); 1130 } 1131 char[] superinterface = superclassInterfaces[i]; 1132 CharOperation.replace(superinterface, '/', '.'); 1133 buffer 1134 .append(returnClassName(superinterface, '.', mode)); 1135 } 1136 } 1137 } 1138 if (!isModule) 1139 buffer.append(Messages.bind(Messages.disassembler_opentypedeclaration)); 1140 if (checkMode(mode, SYSTEM)) { 1141 disassemble(classFileReader.getConstantPool(), buffer, lineSeparator, 1); 1142 } 1143 if (isModule && moduleAttribute != null) { // print attributes - module package and main class only if the mandatory module attribute non-null 1144 decodeModifiersForModule(buffer, accessFlags); 1145 buffer.append("module"); //$NON-NLS-1$ 1146 buffer.append(Messages.disassembler_space); 1147 buffer.append(moduleAttribute.getModuleName()); 1148 buffer.append(Messages.disassembler_space); 1149 buffer.append(Messages.bind(Messages.disassembler_opentypedeclaration)); 1150 disassembleModule(moduleAttribute, buffer, lineSeparator, 1); 1151 IModulePackagesAttribute modulePackagesAttribute = (IModulePackagesAttribute) Util.getAttribute(classFileReader, IAttributeNamesConstants.MODULE_PACKAGES); 1152 disassembleModule(modulePackagesAttribute, buffer, lineSeparator, 1); 1153 IModuleMainClassAttribute mainClassAttribute = (IModuleMainClassAttribute) Util.getAttribute(classFileReader, IAttributeNamesConstants.MODULE_MAIN_CLASS); 1154 disassembleModule(mainClassAttribute, buffer, lineSeparator, 1); 1155 } 1156 disassembleTypeMembers(classFileReader, className, buffer, lineSeparator, 1, mode, isEnum); 1157 if (checkMode(mode, SYSTEM | DETAILED)) { 1158 IClassFileAttribute[] attributes = classFileReader.getAttributes(); 1159 int length = attributes.length; 1160 IEnclosingMethodAttribute enclosingMethodAttribute = (IEnclosingMethodAttribute) Util.getAttribute(classFileReader, IAttributeNamesConstants.ENCLOSING_METHOD); 1161 INestHostAttribute nestHostAttribute = (INestHostAttribute) Util.getAttribute(classFileReader, IAttributeNamesConstants.NEST_HOST); 1162 int remainingAttributesLength = length; 1163 if (innerClassesAttribute != null) { 1164 remainingAttributesLength--; 1165 } 1166 if (enclosingMethodAttribute != null) { 1167 remainingAttributesLength--; 1168 } 1169 if (sourceAttribute != null) { 1170 remainingAttributesLength--; 1171 } 1172 if (signatureAttribute != null) { 1173 remainingAttributesLength--; 1174 } 1175 if (bootstrapMethods != null) { 1176 remainingAttributesLength--; 1177 } 1178 if (moduleAttribute != null) { 1179 remainingAttributesLength--; 1180 } 1181 if (nestHostAttribute != null) { 1182 remainingAttributesLength--; 1183 } 1184 if (nestMembersAttribute != null) { 1185 remainingAttributesLength--; 1186 } 1187 if (innerClassesAttribute != null 1188 || enclosingMethodAttribute != null 1189 || nestHostAttribute != null 1190 || nestMembersAttribute != null 1191 || bootstrapMethods != null 1192 || moduleAttribute != null 1193 || recordAttribute != null 1194 || remainingAttributesLength != 0) { 1195 // this test is to ensure we don't insert more than one line separator 1196 if (buffer.lastIndexOf(lineSeparator) != buffer.length() - lineSeparator.length()) { 1197 writeNewLine(buffer, lineSeparator, 0); 1198 } 1199 } 1200 if (innerClassesAttribute != null) { 1201 disassemble(innerClassesAttribute, buffer, lineSeparator, 1); 1202 } 1203 if (enclosingMethodAttribute != null) { 1204 disassemble(enclosingMethodAttribute, buffer, lineSeparator, 0); 1205 } 1206 if (nestHostAttribute != null) { 1207 disassemble(nestHostAttribute, buffer, lineSeparator, 0); 1208 } 1209 if (nestMembersAttribute != null) { 1210 disassemble(nestMembersAttribute, buffer, lineSeparator, 0); 1211 } 1212 if (recordAttribute != null) { 1213 disassemble(recordAttribute, buffer, lineSeparator, 0, mode); 1214 } 1215 if (bootstrapMethods != null) { 1216 disassemble((IBootstrapMethodsAttribute) bootstrapMethods, buffer, lineSeparator, 0, classFileReader.getConstantPool()); 1217 } 1218 if (checkMode(mode, SYSTEM)) { 1219 if (runtimeVisibleAnnotationsAttribute != null) { 1220 disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 0, mode); 1221 } 1222 if (runtimeInvisibleAnnotationsAttribute != null) { 1223 disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 0, mode); 1224 } 1225 if (runtimeVisibleTypeAnnotationsAttribute != null) { 1226 disassemble((IRuntimeVisibleTypeAnnotationsAttribute) runtimeVisibleTypeAnnotationsAttribute, buffer, lineSeparator, 0, mode); 1227 } 1228 if (runtimeInvisibleTypeAnnotationsAttribute != null) { 1229 disassemble((IRuntimeInvisibleTypeAnnotationsAttribute) runtimeInvisibleTypeAnnotationsAttribute, buffer, lineSeparator, 0, mode); 1230 } 1231 if (length != 0) { 1232 for (int i = 0; i < length; i++) { 1233 IClassFileAttribute attribute = attributes[i]; 1234 if (attribute != innerClassesAttribute 1235 && attribute != nestHostAttribute 1236 && attribute != nestMembersAttribute 1237 && attribute != recordAttribute 1238 && attribute != sourceAttribute 1239 && attribute != signatureAttribute 1240 && attribute != enclosingMethodAttribute 1241 && attribute != runtimeInvisibleAnnotationsAttribute 1242 && attribute != runtimeVisibleAnnotationsAttribute 1243 && attribute != runtimeInvisibleTypeAnnotationsAttribute 1244 && attribute != runtimeVisibleTypeAnnotationsAttribute 1245 && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED) 1246 && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC) 1247 && attribute != bootstrapMethods 1248 && attribute != moduleAttribute 1249 ) { 1250 disassemble(attribute, buffer, lineSeparator, 0, mode); 1251 } 1252 } 1253 } 1254 } 1255 } 1256 writeNewLine(buffer, lineSeparator, 0); 1257 buffer.append(Messages.disassembler_closetypedeclaration); 1258 return buffer.toString(); 1259 } 1260 disassembleModule(IModuleAttribute moduleAttribute, StringBuffer buffer, String lineSeparator, int tabNumber)1261 private void disassembleModule(IModuleAttribute moduleAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { 1262 writeNewLine(buffer, lineSeparator, tabNumber); 1263 char[] moduleVersion = moduleAttribute.getModuleVersionValue(); 1264 if (moduleVersion == null) { 1265 moduleVersion = Messages.disassembler_module_version_none.toCharArray(); 1266 } 1267 buffer.append(Messages.bind(Messages.disassembler_module_version, new String(moduleVersion))); 1268 IRequiresInfo[] requiresInfo = moduleAttribute.getRequiresInfo(); 1269 if (requiresInfo.length > 0) { 1270 writeNewLine(buffer, lineSeparator, 0); 1271 for (int i = 0, max = requiresInfo.length; i < max; i++) { 1272 writeNewLine(buffer, lineSeparator, tabNumber); 1273 disassemble(requiresInfo[i], buffer, lineSeparator, tabNumber); 1274 } 1275 } 1276 IPackageVisibilityInfo[] exportInfos = moduleAttribute.getExportsInfo(); 1277 if (exportInfos.length > 0) { 1278 writeNewLine(buffer, lineSeparator, 0); 1279 for (int i = 0, max = exportInfos.length; i < max; i++) { 1280 writeNewLine(buffer, lineSeparator, tabNumber); 1281 disassemble(exportInfos[i], buffer, lineSeparator, tabNumber, true); 1282 } 1283 } 1284 IPackageVisibilityInfo[] opensInfos = moduleAttribute.getOpensInfo(); 1285 if (opensInfos.length > 0) { 1286 writeNewLine(buffer, lineSeparator, 0); 1287 for (int i = 0, max = opensInfos.length; i < max; i++) { 1288 writeNewLine(buffer, lineSeparator, tabNumber); 1289 disassemble(opensInfos[i], buffer, lineSeparator, tabNumber, false); 1290 } 1291 } 1292 char[][] usesNames = moduleAttribute.getUsesClassNames(); 1293 if (usesNames.length > 0) { 1294 writeNewLine(buffer, lineSeparator, 0); 1295 for (int i = 0, max = usesNames.length; i < max; i++) { 1296 writeNewLine(buffer, lineSeparator, tabNumber); 1297 buffer.append("uses " + CharOperation.charToString(CharOperation.replaceOnCopy(usesNames[i], '/','.'))); //$NON-NLS-1$ 1298 } 1299 } 1300 IProvidesInfo[] providesInfos = moduleAttribute.getProvidesInfo(); 1301 if (providesInfos.length > 0) { 1302 writeNewLine(buffer, lineSeparator, 0); 1303 for (int i = 0, max = providesInfos.length; i < max; i++) { 1304 writeNewLine(buffer, lineSeparator, tabNumber); 1305 disassemble(providesInfos[i], buffer, lineSeparator, tabNumber); 1306 } 1307 } 1308 } convertModuleNames(StringBuffer buffer, char[] name)1309 private void convertModuleNames(StringBuffer buffer, char[] name) { 1310 buffer.append(CharOperation.replaceOnCopy(CharOperation.replaceOnCopy(name, '$','.'), '/','.')); 1311 } 1312 disassembleModule(IModulePackagesAttribute modulePackagesAttribute, StringBuffer buffer, String lineSeparator, int tabNumber)1313 private void disassembleModule(IModulePackagesAttribute modulePackagesAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { 1314 if (modulePackagesAttribute == null) return; 1315 writeNewLine(buffer, lineSeparator, tabNumber); 1316 writeNewLine(buffer, lineSeparator, tabNumber); 1317 buffer.append(Messages.disassembler_modulepackagesattributeheader); 1318 char[][] names = modulePackagesAttribute.getPackageNames(); 1319 for (int i = 0, l = modulePackagesAttribute.getPackagesCount(); i < l; ++i) { 1320 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1321 convertModuleNames(buffer, names[i]); 1322 } 1323 writeNewLine(buffer, lineSeparator, 0); 1324 } 1325 disassembleModule(IModuleMainClassAttribute moduleMainClassAttribute, StringBuffer buffer, String lineSeparator, int tabNumber)1326 private void disassembleModule(IModuleMainClassAttribute moduleMainClassAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { 1327 if (moduleMainClassAttribute == null) return; 1328 writeNewLine(buffer, lineSeparator, tabNumber); 1329 buffer.append(Messages.disassembler_modulemainclassattributeheader); 1330 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1331 convertModuleNames(buffer, moduleMainClassAttribute.getMainClassName()); 1332 writeNewLine(buffer, lineSeparator, 0); 1333 } 1334 disassemble(IProvidesInfo iProvidesInfo, StringBuffer buffer, String lineSeparator, int tabNumber)1335 private void disassemble(IProvidesInfo iProvidesInfo, StringBuffer buffer, String lineSeparator, int tabNumber) { 1336 buffer.append("provides"); //$NON-NLS-1$ 1337 buffer.append(Messages.disassembler_space); 1338 convertModuleNames(buffer, iProvidesInfo.getServiceName()); 1339 buffer.append(Messages.disassembler_space); 1340 char[][] implementations = iProvidesInfo.getImplementationNames(); 1341 if (implementations.length > 0) { 1342 buffer.append( "with"); //$NON-NLS-1$ 1343 buffer.append(Messages.disassembler_space); 1344 for (int i = 0, l = implementations.length; i < l; ++i) { 1345 if (i != 0) { 1346 buffer 1347 .append(Messages.disassembler_comma) 1348 .append(Messages.disassembler_space); 1349 } 1350 convertModuleNames(buffer, implementations[i]); 1351 } 1352 } 1353 buffer.append(';'); 1354 } 1355 disassemble(INestHostAttribute nestHostAttribute, StringBuffer buffer, String lineSeparator, int tabNumber)1356 private void disassemble(INestHostAttribute nestHostAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { 1357 writeNewLine(buffer, lineSeparator, tabNumber); 1358 writeNewLine(buffer, lineSeparator, tabNumber); // additional line 1359 buffer.append(Messages.disassembler_nesthost); 1360 buffer 1361 .append(Messages.disassembler_constantpoolindex) 1362 .append(nestHostAttribute.getNestHostIndex()) 1363 .append(" ")//$NON-NLS-1$ 1364 .append(nestHostAttribute.getNestHostName()); 1365 } disassemble(IRecordAttribute recordAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)1366 private void disassemble(IRecordAttribute recordAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 1367 writeNewLine(buffer, lineSeparator, tabNumber); 1368 writeNewLine(buffer, lineSeparator, tabNumber); // additional line 1369 buffer.append(Messages.disassembler_record); 1370 buffer 1371 .append(Messages.disassembler_constantpoolindex) 1372 .append(recordAttribute.getAttributeName()); 1373 writeNewLine(buffer, lineSeparator, tabNumber); 1374 buffer.append(Messages.disassembler_components); 1375 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1376 IComponentInfo[] entries = recordAttribute.getComponentInfos(); 1377 for (IComponentInfo e : entries) { 1378 disassemble(e, buffer, lineSeparator, tabNumber, mode); 1379 } 1380 } disassemble(IComponentInfo componentInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)1381 private void disassemble(IComponentInfo componentInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 1382 writeNewLine(buffer, lineSeparator, tabNumber); 1383 final char[] descriptor = componentInfo.getDescriptor(); 1384 final ISignatureAttribute signatureAttribute = (ISignatureAttribute) Util.getAttribute(componentInfo, IAttributeNamesConstants.SIGNATURE); 1385 if (checkMode(mode, SYSTEM | DETAILED)) { 1386 buffer.append(Messages.bind(Messages.classfileformat_componentdescriptor, 1387 new String[] { 1388 Integer.toString(componentInfo.getDescriptorIndex()), 1389 new String(descriptor) 1390 })); 1391 writeNewLine(buffer, lineSeparator, tabNumber); 1392 if (signatureAttribute != null) { 1393 buffer.append(Messages.bind(Messages.disassembler_signatureattributeheader, new String(signatureAttribute.getSignature()))); 1394 writeNewLine(buffer, lineSeparator, tabNumber); 1395 } 1396 } 1397 final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(componentInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS); 1398 final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(componentInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS); 1399 final IClassFileAttribute runtimeVisibleTypeAnnotationsAttribute = Util.getAttribute(componentInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS); 1400 final IClassFileAttribute runtimeInvisibleTypeAnnotationsAttribute = Util.getAttribute(componentInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS); 1401 if (checkMode(mode, DETAILED)) { 1402 // disassemble compact version of annotations 1403 if (runtimeInvisibleAnnotationsAttribute != null) { 1404 disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 1405 writeNewLine(buffer, lineSeparator, tabNumber); 1406 } 1407 if (runtimeVisibleAnnotationsAttribute != null) { 1408 disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 1409 writeNewLine(buffer, lineSeparator, tabNumber); 1410 } 1411 } 1412 if (checkMode(mode, WORKING_COPY)) { 1413 if (signatureAttribute != null) { 1414 buffer.append(returnClassName(getSignatureForComponent(signatureAttribute.getSignature()), '.', mode)); 1415 } else { 1416 buffer.append(returnClassName(getSignatureForComponent(descriptor), '.', mode)); 1417 } 1418 } else { 1419 buffer.append(returnClassName(getSignatureForComponent(descriptor), '.', mode)); 1420 } 1421 buffer.append(' '); 1422 buffer.append(new String(componentInfo.getName())); 1423 1424 buffer.append(Messages.disassembler_endofcomponent); 1425 if (checkMode(mode, SYSTEM)) { 1426 IClassFileAttribute[] attributes = componentInfo.getAttributes(); 1427 int length = attributes.length; 1428 if (length != 0) { 1429 for (int i = 0; i < length; i++) { 1430 IClassFileAttribute attribute = attributes[i]; 1431 if (attribute != signatureAttribute 1432 && attribute != runtimeInvisibleAnnotationsAttribute 1433 && attribute != runtimeVisibleAnnotationsAttribute 1434 && attribute != runtimeInvisibleTypeAnnotationsAttribute 1435 && attribute != runtimeVisibleTypeAnnotationsAttribute) { 1436 disassemble(attribute, buffer, lineSeparator, tabNumber, mode); 1437 } 1438 } 1439 } 1440 if (runtimeVisibleAnnotationsAttribute != null) { 1441 disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 1442 } 1443 if (runtimeInvisibleAnnotationsAttribute != null) { 1444 disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 1445 } 1446 if (runtimeVisibleTypeAnnotationsAttribute != null) { 1447 disassemble((IRuntimeVisibleTypeAnnotationsAttribute) runtimeVisibleTypeAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 1448 } 1449 if (runtimeInvisibleTypeAnnotationsAttribute != null) { 1450 disassemble((IRuntimeInvisibleTypeAnnotationsAttribute) runtimeInvisibleTypeAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 1451 } 1452 } 1453 } 1454 disassemble(INestMembersAttribute nestMembersAttribute, StringBuffer buffer, String lineSeparator, int tabNumber)1455 private void disassemble(INestMembersAttribute nestMembersAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { 1456 writeNewLine(buffer, lineSeparator, tabNumber); 1457 writeNewLine(buffer, lineSeparator, tabNumber); // additional line 1458 buffer.append(Messages.disassembler_nestmembers); 1459 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1460 INestMemberAttributeEntry[] entries = nestMembersAttribute.getNestMemberAttributesEntries(); 1461 int length = entries.length; 1462 int nestMemberIndex; 1463 INestMemberAttributeEntry entry; 1464 for (int i = 0; i < length; i++) { 1465 if (i != 0) { 1466 buffer.append(Messages.disassembler_comma); 1467 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1468 } 1469 entry = entries[i]; 1470 nestMemberIndex = entry.getNestMemberIndex(); 1471 buffer 1472 .append(Messages.disassembler_constantpoolindex) 1473 .append(nestMemberIndex); 1474 if (nestMemberIndex != 0) { 1475 buffer 1476 .append(Messages.disassembler_space) 1477 .append(entry.getNestMemberName()); 1478 } 1479 } 1480 } disassemble(IPackageVisibilityInfo iPackageVisibilityInfo, StringBuffer buffer, String lineSeparator, int tabNumber, boolean isExports)1481 private void disassemble(IPackageVisibilityInfo iPackageVisibilityInfo, StringBuffer buffer, String lineSeparator, 1482 int tabNumber, boolean isExports) { 1483 buffer.append(isExports ? "exports" : "opens"); //$NON-NLS-1$ //$NON-NLS-2$ 1484 buffer.append(Messages.disassembler_space); 1485 convertModuleNames(buffer, iPackageVisibilityInfo.getPackageName()); 1486 char[][] targets = iPackageVisibilityInfo.getTargetModuleNames(); 1487 if (targets.length > 0) { 1488 buffer.append(Messages.disassembler_space); 1489 buffer.append( "to"); //$NON-NLS-1$ 1490 buffer.append(Messages.disassembler_space); 1491 for (int i = 0, l = targets.length; i < l; ++i) { 1492 if (i != 0) { 1493 buffer 1494 .append(Messages.disassembler_comma) 1495 .append(Messages.disassembler_space); 1496 } 1497 buffer.append(targets[i]); 1498 } 1499 } 1500 buffer.append(';'); 1501 } 1502 disassemble(IRequiresInfo iRequiresInfo, StringBuffer buffer, String lineSeparator, int tabNumber)1503 private void disassemble(IRequiresInfo iRequiresInfo, StringBuffer buffer, String lineSeparator, int tabNumber) { 1504 buffer.append("requires "); //$NON-NLS-1$ 1505 decodeModifiersForModuleRequires(buffer, iRequiresInfo.getRequiresFlags()); 1506 buffer.append(iRequiresInfo.getRequiresModuleName()); 1507 buffer.append(';'); 1508 } 1509 disassembleGenericSignature(int mode, StringBuffer buffer, final char[] signature)1510 private void disassembleGenericSignature(int mode, StringBuffer buffer, final char[] signature) { 1511 CharOperation.replace(signature, '/', '.'); 1512 final char[][] typeParameters = Signature.getTypeParameters(signature); 1513 final int typeParametersLength = typeParameters.length; 1514 if (typeParametersLength != 0) { 1515 buffer.append('<'); 1516 for (int i = 0; i < typeParametersLength; i++) { 1517 if (i != 0) { 1518 buffer.append(Messages.disassembler_comma); 1519 } 1520 // extract the name 1521 buffer.append(typeParameters[i], 0, CharOperation.indexOf(':', typeParameters[i])); 1522 final char[][] bounds = Signature.getTypeParameterBounds(typeParameters[i]); 1523 final int boundsLength = bounds.length; 1524 if (boundsLength != 0) { 1525 if (boundsLength == 1) { 1526 final char[] bound = bounds[0]; 1527 // check if this is java.lang.Object 1528 if (!isJavaLangObject(Signature.toCharArray(bound))) { 1529 buffer.append(" extends "); //$NON-NLS-1$ 1530 buffer.append(returnClassName(Signature.toCharArray(bound), '.', mode)); 1531 } 1532 } else { 1533 buffer.append(" extends "); //$NON-NLS-1$ 1534 for (int j= 0; j < boundsLength; j++) { 1535 if (j != 0) { 1536 buffer.append(" & "); //$NON-NLS-1$ 1537 } 1538 buffer.append(returnClassName(Signature.toCharArray(bounds[j]), '.', mode)); 1539 } 1540 } 1541 } 1542 } 1543 buffer.append('>'); 1544 } 1545 } 1546 isJavaLangObject(final char[] className)1547 private boolean isJavaLangObject(final char[] className) { 1548 return CharOperation.equals(TypeConstants.JAVA_LANG_OBJECT, CharOperation.splitOn('.', className)); 1549 } 1550 1551 isVarArgs(IMethodInfo methodInfo)1552 private boolean isVarArgs(IMethodInfo methodInfo) { 1553 int accessFlags = methodInfo.getAccessFlags(); 1554 if ((accessFlags & IModifierConstants.ACC_VARARGS) != 0) return true; 1555 // check the presence of the unspecified Varargs attribute 1556 return Util.getAttribute(methodInfo, AttributeNamesConstants.VarargsName) != null; 1557 } disassemble(ICodeAttribute codeAttribute, char[][] parameterNames, char[] methodDescriptor, boolean isStatic, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)1558 private void disassemble(ICodeAttribute codeAttribute, char[][] parameterNames, char[] methodDescriptor, boolean isStatic, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 1559 writeNewLine(buffer, lineSeparator, tabNumber - 1); 1560 DefaultBytecodeVisitor visitor = new DefaultBytecodeVisitor(codeAttribute, parameterNames, methodDescriptor, isStatic, buffer, lineSeparator, tabNumber, mode); 1561 try { 1562 codeAttribute.traverse(visitor); 1563 } catch(ClassFormatException e) { 1564 dumpTab(tabNumber + 3, buffer); 1565 buffer.append(Messages.classformat_classformatexception); 1566 writeNewLine(buffer, lineSeparator, tabNumber - 1); 1567 } 1568 final int exceptionTableLength = codeAttribute.getExceptionTableLength(); 1569 boolean isFirstAttribute = true; 1570 if (exceptionTableLength != 0) { 1571 final int tabNumberForExceptionAttribute = tabNumber + 2; 1572 isFirstAttribute = false; 1573 dumpTab(tabNumberForExceptionAttribute, buffer); 1574 final IExceptionTableEntry[] exceptionTableEntries = codeAttribute.getExceptionTable(); 1575 buffer.append(Messages.disassembler_exceptiontableheader); 1576 writeNewLine(buffer, lineSeparator, tabNumberForExceptionAttribute + 1); 1577 for (int i = 0; i < exceptionTableLength; i++) { 1578 if (i != 0) { 1579 writeNewLine(buffer, lineSeparator, tabNumberForExceptionAttribute + 1); 1580 } 1581 IExceptionTableEntry exceptionTableEntry = exceptionTableEntries[i]; 1582 char[] catchType; 1583 if (exceptionTableEntry.getCatchTypeIndex() != 0) { 1584 catchType = exceptionTableEntry.getCatchType(); 1585 CharOperation.replace(catchType, '/', '.'); 1586 catchType = returnClassName(catchType, '.', mode); 1587 } else { 1588 catchType = ANY_EXCEPTION; 1589 } 1590 buffer.append(Messages.bind(Messages.classfileformat_exceptiontableentry, 1591 new String[] { 1592 Integer.toString(exceptionTableEntry.getStartPC()), 1593 Integer.toString(exceptionTableEntry.getEndPC()), 1594 Integer.toString(exceptionTableEntry.getHandlerPC()), 1595 new String(catchType), 1596 })); 1597 } 1598 } 1599 final ILineNumberAttribute lineNumberAttribute = codeAttribute.getLineNumberAttribute(); 1600 final int lineAttributeLength = lineNumberAttribute == null ? 0 : lineNumberAttribute.getLineNumberTableLength(); 1601 if (lineAttributeLength != 0) { 1602 int tabNumberForLineAttribute = tabNumber + 2; 1603 if (!isFirstAttribute) { 1604 writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute); 1605 } else { 1606 dumpTab(tabNumberForLineAttribute, buffer); 1607 isFirstAttribute = false; 1608 } 1609 buffer.append(Messages.disassembler_linenumberattributeheader); 1610 writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute + 1); 1611 int[][] lineattributesEntries = lineNumberAttribute.getLineNumberTable(); 1612 for (int i = 0; i < lineAttributeLength; i++) { 1613 if (i != 0) { 1614 writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute + 1); 1615 } 1616 buffer.append(Messages.bind(Messages.classfileformat_linenumbertableentry, 1617 new String[] { 1618 Integer.toString(lineattributesEntries[i][0]), 1619 Integer.toString(lineattributesEntries[i][1]) 1620 })); 1621 } 1622 } 1623 final ILocalVariableAttribute localVariableAttribute = codeAttribute.getLocalVariableAttribute(); 1624 final int localVariableAttributeLength = localVariableAttribute == null ? 0 : localVariableAttribute.getLocalVariableTableLength(); 1625 if (localVariableAttributeLength != 0) { 1626 int tabNumberForLocalVariableAttribute = tabNumber + 2; 1627 if (!isFirstAttribute) { 1628 writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute); 1629 } else { 1630 isFirstAttribute = false; 1631 dumpTab(tabNumberForLocalVariableAttribute, buffer); 1632 } 1633 buffer.append(Messages.disassembler_localvariabletableattributeheader); 1634 writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1); 1635 ILocalVariableTableEntry[] localVariableTableEntries = localVariableAttribute.getLocalVariableTable(); 1636 for (int i = 0; i < localVariableAttributeLength; i++) { 1637 if (i != 0) { 1638 writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1); 1639 } 1640 ILocalVariableTableEntry localVariableTableEntry = localVariableTableEntries[i]; 1641 int index= localVariableTableEntry.getIndex(); 1642 int startPC = localVariableTableEntry.getStartPC(); 1643 int length = localVariableTableEntry.getLength(); 1644 final char[] typeName = Signature.toCharArray(localVariableTableEntry.getDescriptor()); 1645 CharOperation.replace(typeName, '/', '.'); 1646 buffer.append(Messages.bind(Messages.classfileformat_localvariabletableentry, 1647 new String[] { 1648 Integer.toString(startPC), 1649 Integer.toString(startPC + length), 1650 new String(localVariableTableEntry.getName()), 1651 Integer.toString(index), 1652 new String(returnClassName(typeName, '.', mode)) 1653 })); 1654 } 1655 } 1656 final ILocalVariableTypeTableAttribute localVariableTypeAttribute= (ILocalVariableTypeTableAttribute) Util.getAttribute(codeAttribute, IAttributeNamesConstants.LOCAL_VARIABLE_TYPE_TABLE); 1657 final int localVariableTypeTableLength = localVariableTypeAttribute == null ? 0 : localVariableTypeAttribute.getLocalVariableTypeTableLength(); 1658 if (localVariableTypeTableLength != 0) { 1659 int tabNumberForLocalVariableAttribute = tabNumber + 2; 1660 if (!isFirstAttribute) { 1661 writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute); 1662 } else { 1663 isFirstAttribute = false; 1664 dumpTab(tabNumberForLocalVariableAttribute, buffer); 1665 } 1666 buffer.append(Messages.disassembler_localvariabletypetableattributeheader); 1667 writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1); 1668 ILocalVariableTypeTableEntry[] localVariableTypeTableEntries = localVariableTypeAttribute.getLocalVariableTypeTable(); 1669 for (int i = 0; i < localVariableTypeTableLength; i++) { 1670 if (i != 0) { 1671 writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1); 1672 } 1673 ILocalVariableTypeTableEntry localVariableTypeTableEntry = localVariableTypeTableEntries[i]; 1674 int index= localVariableTypeTableEntry.getIndex(); 1675 int startPC = localVariableTypeTableEntry.getStartPC(); 1676 int length = localVariableTypeTableEntry.getLength(); 1677 final char[] typeName = Signature.toCharArray(localVariableTypeTableEntry.getSignature()); 1678 CharOperation.replace(typeName, '/', '.'); 1679 buffer.append(Messages.bind(Messages.classfileformat_localvariabletableentry, 1680 new String[] { 1681 Integer.toString(startPC), 1682 Integer.toString(startPC + length), 1683 new String(localVariableTypeTableEntry.getName()), 1684 Integer.toString(index), 1685 new String(returnClassName(typeName, '.', mode)) 1686 })); 1687 } 1688 } 1689 final int length = codeAttribute.getAttributesCount(); 1690 if (length != 0) { 1691 IClassFileAttribute[] attributes = codeAttribute.getAttributes(); 1692 for (int i = 0; i < length; i++) { 1693 IClassFileAttribute attribute = attributes[i]; 1694 if (CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.STACK_MAP_TABLE)) { 1695 IStackMapTableAttribute stackMapTableAttribute = (IStackMapTableAttribute) attribute; 1696 if (!isFirstAttribute) { 1697 writeNewLine(buffer, lineSeparator, tabNumber + 2); 1698 } else { 1699 isFirstAttribute = false; 1700 dumpTab(tabNumber + 1, buffer); 1701 } 1702 int numberOfEntries = stackMapTableAttribute.getNumberOfEntries(); 1703 buffer.append(Messages.bind(Messages.disassembler_stackmaptableattributeheader, Integer.toString(numberOfEntries))); 1704 if (numberOfEntries != 0) { 1705 disassemble(stackMapTableAttribute, buffer, lineSeparator, tabNumber, mode); 1706 } 1707 } else if (CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.STACK_MAP)) { 1708 IStackMapAttribute stackMapAttribute = (IStackMapAttribute) attribute; 1709 if (!isFirstAttribute) { 1710 writeNewLine(buffer, lineSeparator, tabNumber + 2); 1711 } else { 1712 isFirstAttribute = false; 1713 dumpTab(tabNumber + 1, buffer); 1714 } 1715 int numberOfEntries = stackMapAttribute.getNumberOfEntries(); 1716 buffer.append(Messages.bind(Messages.disassembler_stackmapattributeheader, Integer.toString(numberOfEntries))); 1717 if (numberOfEntries != 0) { 1718 disassemble(stackMapAttribute, buffer, lineSeparator, tabNumber, mode); 1719 } 1720 } else if (CharOperation.equals(attribute.getAttributeName(),IAttributeNamesConstants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS)) { 1721 disassemble((IRuntimeVisibleTypeAnnotationsAttribute) attribute, buffer, lineSeparator, tabNumber, mode); 1722 } else if (CharOperation.equals(attribute.getAttributeName(),IAttributeNamesConstants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS)) { 1723 disassemble((IRuntimeInvisibleTypeAnnotationsAttribute) attribute, buffer, lineSeparator, tabNumber, mode); 1724 } else if (attribute != lineNumberAttribute 1725 && attribute != localVariableAttribute 1726 && attribute != localVariableTypeAttribute) { 1727 if (!isFirstAttribute) { 1728 writeNewLine(buffer, lineSeparator, tabNumber + 2); 1729 } else { 1730 isFirstAttribute = false; 1731 dumpTab(tabNumber + 1, buffer); 1732 } 1733 buffer.append(Messages.bind(Messages.disassembler_genericattributeheader, 1734 new String[] { 1735 new String(attribute.getAttributeName()), 1736 Long.toString(attribute.getAttributeLength()) 1737 })); 1738 } 1739 } 1740 } 1741 } 1742 disassemble(IStackMapTableAttribute attribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)1743 private void disassemble(IStackMapTableAttribute attribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 1744 writeNewLine(buffer, lineSeparator, tabNumber + 3); 1745 int numberOfEntries = attribute.getNumberOfEntries(); 1746 final IStackMapFrame[] stackMapFrames = attribute.getStackMapFrame(); 1747 int absolutePC = -1; 1748 for (int j = 0; j < numberOfEntries; j++) { 1749 if (j > 0) { 1750 writeNewLine(buffer, lineSeparator, tabNumber + 3); 1751 } 1752 final IStackMapFrame frame = stackMapFrames[j]; 1753 // disassemble each frame 1754 int type = frame.getFrameType(); 1755 int offsetDelta = frame.getOffsetDelta(); 1756 if (absolutePC == -1) { 1757 absolutePC = offsetDelta; 1758 } else { 1759 absolutePC += (offsetDelta + 1); 1760 } 1761 switch(type) { 1762 case 247 : // SAME_LOCALS_1_STACK_ITEM_EXTENDED 1763 buffer.append( 1764 Messages.bind( 1765 Messages.disassembler_frame_same_locals_1_stack_item_extended, 1766 Integer.toString(absolutePC), 1767 disassemble(frame.getStackItems(), mode))); 1768 break; 1769 case 248 : 1770 case 249 : 1771 case 250: 1772 // CHOP 1773 buffer.append( 1774 Messages.bind( 1775 Messages.disassembler_frame_chop, 1776 Integer.toString(absolutePC), 1777 Integer.toString(251 - type))); 1778 break; 1779 case 251 : 1780 // SAME_FRAME_EXTENDED 1781 buffer.append( 1782 Messages.bind( 1783 Messages.disassembler_frame_same_frame_extended, 1784 Integer.toString(absolutePC))); 1785 break; 1786 case 252 : 1787 case 253 : 1788 case 254 : 1789 // APPEND 1790 buffer.append( 1791 Messages.bind( 1792 Messages.disassembler_frame_append, 1793 Integer.toString(absolutePC), 1794 disassemble(frame.getLocals(), mode))); 1795 break; 1796 case 255 : 1797 // FULL_FRAME 1798 buffer.append( 1799 Messages.bind( 1800 Messages.disassembler_frame_full_frame, 1801 new String[] { 1802 Integer.toString(absolutePC), 1803 Integer.toString(frame.getNumberOfLocals()), 1804 disassemble(frame.getLocals(), mode), 1805 Integer.toString(frame.getNumberOfStackItems()), 1806 disassemble(frame.getStackItems(), mode), 1807 dumpNewLineWithTabs(lineSeparator, tabNumber + 5) 1808 })); 1809 break; 1810 default: 1811 if (type <= 63) { 1812 // SAME_FRAME 1813 offsetDelta = type; 1814 buffer.append( 1815 Messages.bind( 1816 Messages.disassembler_frame_same_frame, 1817 Integer.toString(absolutePC))); 1818 } else if (type <= 127) { 1819 // SAME_LOCALS_1_STACK_ITEM 1820 offsetDelta = type - 64; 1821 buffer.append( 1822 Messages.bind( 1823 Messages.disassembler_frame_same_locals_1_stack_item, 1824 Integer.toString(absolutePC), 1825 disassemble(frame.getStackItems(), mode))); 1826 } 1827 } 1828 } 1829 } 1830 disassemble(IStackMapAttribute attribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)1831 private void disassemble(IStackMapAttribute attribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 1832 writeNewLine(buffer, lineSeparator, tabNumber + 3); 1833 int numberOfEntries = attribute.getNumberOfEntries(); 1834 final IStackMapFrame[] stackMapFrames = attribute.getStackMapFrame(); 1835 for (int j = 0; j < numberOfEntries; j++) { 1836 if (j > 0) { 1837 writeNewLine(buffer, lineSeparator, tabNumber + 3); 1838 } 1839 final IStackMapFrame frame = stackMapFrames[j]; 1840 // disassemble each frame 1841 buffer.append( 1842 Messages.bind( 1843 Messages.disassembler_frame_full_frame, 1844 new String[] { 1845 Integer.toString(frame.getOffsetDelta()), 1846 Integer.toString(frame.getNumberOfLocals()), 1847 disassemble(frame.getLocals(), mode), 1848 Integer.toString(frame.getNumberOfStackItems()), 1849 disassemble(frame.getStackItems(), mode), 1850 dumpNewLineWithTabs(lineSeparator, tabNumber + 5) 1851 })); 1852 } 1853 } 1854 bootstrapMethodDescription(IBootstrapMethodsEntry entry, IConstantPool constantPool)1855 private String bootstrapMethodDescription(IBootstrapMethodsEntry entry, IConstantPool constantPool) { 1856 // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html 1857 // The BootstrapMethods attribute records bootstrap method specifiers referenced by invokedynamic instructions. 1858 // The value of the bootstrap_method_ref item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_MethodHandle_info structure (§4.4.8). 1859 // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.8 1860 // constantpoolentry.getKind() = IConstantPoolConstant.CONSTANT_MethodHandle 1861 1862 ConstantPoolEntry2 constantPoolEntry2 = (ConstantPoolEntry2) constantPool.decodeEntry(entry.getBootstrapMethodReference()); 1863 1864 // The reference_kind item of the CONSTANT_MethodHandle_info structure should have the value 6 (REF_invokeStatic) or 8 (REF_newInvokeSpecial) 1865 // (§5.4.3.5) or else invocation of the bootstrap method handle during call site specifier resolution for an invokedynamic instruction will complete abruptly. 1866 // If the value of the reference_kind item is 5 (REF_invokeVirtual), 6 (REF_invokeStatic), 7 (REF_invokeSpecial), 1867 // or 9 (REF_invokeInterface), the name of the method represented by a CONSTANT_Methodref_info structure must not be <init> or <clinit>. 1868 1869 if (constantPoolEntry2.getReferenceKind() != 6) 1870 return null; 1871 ConstantPoolEntry constantPoolEntry = (ConstantPoolEntry) constantPool.decodeEntry(constantPoolEntry2.getReferenceIndex()); 1872 StringBuilder builder = new StringBuilder(); 1873 //String[] methodMsg = methodDescription(constantPoolEntry); 1874 builder.append(Messages.bind("invokestatic {0}.{1}:{2}", methodDescription(constantPoolEntry))); //$NON-NLS-1$ 1875 return builder.toString(); 1876 } 1877 bootstrapArgumentsDescription(IBootstrapMethodsEntry entry, IConstantPool constantPool)1878 private String[] bootstrapArgumentsDescription(IBootstrapMethodsEntry entry, IConstantPool constantPool) { 1879 // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.21 1880 // bootstrap_arguments 1881 // Each entry in the bootstrap_arguments array must be a valid index into the constant_pool table. 1882 // The constant_pool entry at that index must be a CONSTANT_String_info, CONSTANT_Class_info, CONSTANT_Integer_info 1883 // CONSTANT_Long_info, CONSTANT_Float_info, CONSTANT_Double_info, CONSTANT_MethodHandle_info, or 1884 // CONSTANT_MethodType_info structure (§4.4.3, §4.4.1, §4.4.4, §4.4.5), §4.4.8, §4.4.9). 1885 if (entry.getBootstrapArguments().length == 0) 1886 return null; 1887 int[] bootstrapArguments = entry.getBootstrapArguments(); 1888 String[] arguments = new String[bootstrapArguments.length]; 1889 for (int i = 0, length = bootstrapArguments.length; i < length; i++) { 1890 ConstantPoolEntry constantPoolEntry = (ConstantPoolEntry) constantPool.decodeEntry(bootstrapArguments[i]); 1891 switch(constantPoolEntry.getKind()) { 1892 case IConstantPoolConstant.CONSTANT_Integer: 1893 arguments[i] = ((Integer) constantPoolEntry.getIntegerValue()).toString(); 1894 break; 1895 case IConstantPoolConstant.CONSTANT_MethodHandle: 1896 // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.8 1897 // If the value of the reference_kind item is 5 (REF_invokeVirtual), 6 (REF_invokeStatic), 1898 // 7 (REF_invokeSpecial), or 8 (REF_newInvokeSpecial), then the constant_pool entry at that 1899 // index must be a CONSTANT_Methodref_info structure (§4.4.2) representing a class's method or 1900 // constructor (§2.9) for which a method handle is to be created. 1901 ConstantPoolEntry2 constantPoolEntry2 = (ConstantPoolEntry2) constantPoolEntry; 1902 StringBuilder builder = new StringBuilder(10); 1903 switch(constantPoolEntry2.getReferenceKind()) { 1904 case IConstantPoolConstant.METHOD_TYPE_REF_GetField: 1905 builder.append("REF_getField "); //$NON-NLS-1$ 1906 constantPoolEntry = (ConstantPoolEntry) constantPool.decodeEntry(constantPoolEntry2.getReferenceIndex()); 1907 builder.append(Messages.bind("{0}:{1}", fieldDescription(constantPoolEntry))); //$NON-NLS-1$ 1908 arguments[i] = builder.toString(); 1909 break; 1910 case IConstantPoolConstant.METHOD_TYPE_REF_InvokeStatic: 1911 builder.append("invokestatic "); //$NON-NLS-1$ 1912 //$FALL-THROUGH$ 1913 case IConstantPoolConstant.METHOD_TYPE_REF_InvokeVirtual: 1914 case IConstantPoolConstant.METHOD_TYPE_REF_NewInvokeSpecial: 1915 constantPoolEntry = (ConstantPoolEntry) constantPool.decodeEntry(constantPoolEntry2.getReferenceIndex()); 1916 builder.append(Messages.bind("{0}.{1}:{2}", methodDescription(constantPoolEntry))); //$NON-NLS-1$ 1917 arguments[i] = builder.toString(); 1918 break; 1919 } 1920 break; 1921 case IConstantPoolConstant.CONSTANT_MethodType: 1922 arguments[i] = new String(((ConstantPoolEntry2) constantPoolEntry).getMethodDescriptor()); 1923 break; 1924 case IConstantPoolConstant.CONSTANT_Class: 1925 arguments[i] = new String(constantPoolEntry.getClassInfoName()); 1926 break; 1927 case IConstantPoolConstant.CONSTANT_String: 1928 arguments[i] = constantPoolEntry.getStringValue(); 1929 break; 1930 } 1931 } 1932 return arguments; 1933 } 1934 fieldDescription(IConstantPoolEntry constantPoolEntry)1935 private String[] fieldDescription(IConstantPoolEntry constantPoolEntry) { 1936 return new String[] { new String(constantPoolEntry.getFieldName()), 1937 new String(constantPoolEntry.getFieldDescriptor())}; 1938 } 1939 methodDescription(IConstantPoolEntry constantPoolEntry)1940 private String[] methodDescription(IConstantPoolEntry constantPoolEntry) { 1941 return new String[] { new String(constantPoolEntry.getClassName()), 1942 new String(constantPoolEntry.getMethodName()), 1943 new String(constantPoolEntry.getMethodDescriptor())}; 1944 } 1945 disassemble(IConstantPool constantPool, StringBuffer buffer, String lineSeparator, int tabNumber)1946 private void disassemble(IConstantPool constantPool, StringBuffer buffer, String lineSeparator, int tabNumber) { 1947 writeNewLine(buffer, lineSeparator, tabNumber); 1948 int length = constantPool.getConstantPoolCount(); 1949 buffer.append(Messages.disassembler_constantpoolheader); 1950 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1951 for (int i = 1; i < length; i++) { 1952 if (i != 1) { 1953 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1954 } 1955 IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(i); 1956 String[] methodDescription; 1957 int kind = constantPool.getEntryKind(i); 1958 switch (kind) { 1959 case IConstantPoolConstant.CONSTANT_Class : 1960 buffer.append( 1961 Messages.bind(Messages.disassembler_constantpool_class, 1962 new String[] { 1963 Integer.toString(i), 1964 Integer.toString(constantPoolEntry.getClassInfoNameIndex()), 1965 new String(constantPoolEntry.getClassInfoName())})); 1966 break; 1967 case IConstantPoolConstant.CONSTANT_Double : 1968 buffer.append( 1969 Messages.bind(Messages.disassembler_constantpool_double, 1970 new String[] { 1971 Integer.toString(i), 1972 Double.toString(constantPoolEntry.getDoubleValue())})); 1973 break; 1974 case IConstantPoolConstant.CONSTANT_Fieldref : 1975 buffer.append( 1976 Messages.bind(Messages.disassembler_constantpool_fieldref, 1977 new String[] { 1978 Integer.toString(i), 1979 Integer.toString(constantPoolEntry.getClassIndex()), 1980 Integer.toString(constantPoolEntry.getNameAndTypeIndex()), 1981 new String(constantPoolEntry.getClassName()), 1982 new String(constantPoolEntry.getFieldName()), 1983 new String(constantPoolEntry.getFieldDescriptor()) 1984 })); 1985 break; 1986 case IConstantPoolConstant.CONSTANT_Float : 1987 buffer.append( 1988 Messages.bind(Messages.disassembler_constantpool_float, 1989 new String[] { 1990 Integer.toString(i), 1991 Float.toString(constantPoolEntry.getFloatValue())})); 1992 break; 1993 case IConstantPoolConstant.CONSTANT_Integer : 1994 buffer.append( 1995 Messages.bind(Messages.disassembler_constantpool_integer, 1996 new String[] { 1997 Integer.toString(i), 1998 Integer.toString(constantPoolEntry.getIntegerValue())})); 1999 break; 2000 case IConstantPoolConstant.CONSTANT_InterfaceMethodref : 2001 methodDescription = methodDescription(constantPoolEntry); 2002 buffer.append( 2003 Messages.bind(Messages.disassembler_constantpool_interfacemethodref, 2004 new String[] { 2005 Integer.toString(i), 2006 Integer.toString(constantPoolEntry.getClassIndex()), 2007 Integer.toString(constantPoolEntry.getNameAndTypeIndex()), 2008 methodDescription[0], methodDescription[1], methodDescription[2]})); 2009 break; 2010 case IConstantPoolConstant.CONSTANT_Long : 2011 buffer.append( 2012 Messages.bind(Messages.disassembler_constantpool_long, 2013 new String[] { 2014 Integer.toString(i), 2015 Long.toString(constantPoolEntry.getLongValue())})); 2016 break; 2017 case IConstantPoolConstant.CONSTANT_Methodref : 2018 methodDescription = methodDescription(constantPoolEntry); 2019 buffer.append( 2020 Messages.bind(Messages.disassembler_constantpool_methodref, 2021 new String[] { 2022 Integer.toString(i), 2023 Integer.toString(constantPoolEntry.getClassIndex()), 2024 Integer.toString(constantPoolEntry.getNameAndTypeIndex()), 2025 methodDescription[0], methodDescription[1], methodDescription[2]})); 2026 break; 2027 case IConstantPoolConstant.CONSTANT_NameAndType : 2028 int nameIndex = constantPoolEntry.getNameAndTypeInfoNameIndex(); 2029 int typeIndex = constantPoolEntry.getNameAndTypeInfoDescriptorIndex(); 2030 IConstantPoolEntry entry = constantPool.decodeEntry(nameIndex); 2031 char[] nameValue = entry.getUtf8Value(); 2032 entry = constantPool.decodeEntry(typeIndex); 2033 char[] typeValue = entry.getUtf8Value(); 2034 buffer.append( 2035 Messages.bind(Messages.disassembler_constantpool_name_and_type, 2036 new String[] { 2037 Integer.toString(i), 2038 Integer.toString(nameIndex), 2039 Integer.toString(typeIndex), 2040 String.valueOf(nameValue), 2041 String.valueOf(typeValue)})); 2042 break; 2043 case IConstantPoolConstant.CONSTANT_String : 2044 buffer.append( 2045 Messages.bind(Messages.disassembler_constantpool_string, 2046 new String[] { 2047 Integer.toString(i), 2048 Integer.toString(constantPoolEntry.getStringIndex()), 2049 decodeStringValue(constantPoolEntry.getStringValue())})); 2050 break; 2051 case IConstantPoolConstant.CONSTANT_Utf8 : 2052 buffer.append( 2053 Messages.bind(Messages.disassembler_constantpool_utf8, 2054 new String[] { 2055 Integer.toString(i), 2056 decodeStringValue(new String(constantPoolEntry.getUtf8Value()))})); 2057 break; 2058 case IConstantPoolConstant.CONSTANT_MethodHandle : 2059 IConstantPoolEntry2 entry2 = (IConstantPoolEntry2) constantPoolEntry; 2060 buffer.append( 2061 Messages.bind(Messages.disassembler_constantpool_methodhandle, 2062 new String[] { 2063 Integer.toString(i), 2064 getReferenceKind(entry2.getReferenceKind()), 2065 Integer.toString(entry2.getReferenceIndex()), 2066 })); 2067 break; 2068 case IConstantPoolConstant.CONSTANT_MethodType : 2069 entry2 = (IConstantPoolEntry2) constantPoolEntry; 2070 buffer.append( 2071 Messages.bind(Messages.disassembler_constantpool_methodtype, 2072 new String[] { 2073 Integer.toString(i), 2074 Integer.toString(entry2.getDescriptorIndex()), 2075 String.valueOf(entry2.getMethodDescriptor()), 2076 })); 2077 break; 2078 case IConstantPoolConstant.CONSTANT_InvokeDynamic : 2079 entry2 = (IConstantPoolEntry2) constantPoolEntry; 2080 buffer.append( 2081 Messages.bind(Messages.disassembler_constantpool_invokedynamic, 2082 new String[] { 2083 Integer.toString(i), 2084 Integer.toString(entry2.getBootstrapMethodAttributeIndex()), 2085 Integer.toString(entry2.getNameAndTypeIndex()), 2086 new String(constantPoolEntry.getMethodName()), 2087 new String(constantPoolEntry.getMethodDescriptor()) 2088 })); 2089 break; 2090 case IConstantPoolConstant.CONSTANT_Dynamic : 2091 entry2 = (IConstantPoolEntry2) constantPoolEntry; 2092 buffer.append( 2093 Messages.bind(Messages.disassembler_constantpool_dynamic, 2094 new String[] { 2095 Integer.toString(i), 2096 Integer.toString(entry2.getBootstrapMethodAttributeIndex()), 2097 Integer.toString(entry2.getNameAndTypeIndex()), 2098 new String(constantPoolEntry.getFieldName()), 2099 new String(constantPoolEntry.getFieldDescriptor()) 2100 })); 2101 break; 2102 } 2103 } 2104 } 2105 getReferenceKind(int referenceKind)2106 private String getReferenceKind(int referenceKind) { 2107 String message = null; 2108 switch(referenceKind) { 2109 case IConstantPoolConstant.METHOD_TYPE_REF_GetField : 2110 message = Messages.disassembler_method_type_ref_getfield; 2111 break; 2112 case IConstantPoolConstant.METHOD_TYPE_REF_GetStatic : 2113 message = Messages.disassembler_method_type_ref_getstatic; 2114 break; 2115 case IConstantPoolConstant.METHOD_TYPE_REF_PutField : 2116 message = Messages.disassembler_method_type_ref_putfield; 2117 break; 2118 case IConstantPoolConstant.METHOD_TYPE_REF_PutStatic : 2119 message = Messages.disassembler_method_type_ref_putstatic; 2120 break; 2121 case IConstantPoolConstant.METHOD_TYPE_REF_InvokeInterface : 2122 message = Messages.disassembler_method_type_ref_invokeinterface; 2123 break; 2124 case IConstantPoolConstant.METHOD_TYPE_REF_InvokeSpecial : 2125 message = Messages.disassembler_method_type_ref_invokespecial; 2126 break; 2127 case IConstantPoolConstant.METHOD_TYPE_REF_InvokeStatic : 2128 message = Messages.disassembler_method_type_ref_invokestatic; 2129 break; 2130 case IConstantPoolConstant.METHOD_TYPE_REF_InvokeVirtual : 2131 message = Messages.disassembler_method_type_ref_invokevirtual; 2132 break; 2133 default : 2134 message = Messages.disassembler_method_type_ref_newinvokespecial; 2135 } 2136 return Messages.bind(message, new String[] { Integer.toString(referenceKind) }); 2137 } 2138 disassemble(IEnclosingMethodAttribute enclosingMethodAttribute, StringBuffer buffer, String lineSeparator, int tabNumber)2139 private void disassemble(IEnclosingMethodAttribute enclosingMethodAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { 2140 writeNewLine(buffer, lineSeparator, tabNumber + 1); 2141 buffer.append(Messages.disassembler_enclosingmethodheader); 2142 buffer 2143 .append(Messages.disassembler_constantpoolindex) 2144 .append(enclosingMethodAttribute.getEnclosingClassIndex()) 2145 .append(" ")//$NON-NLS-1$ 2146 .append(Messages.disassembler_constantpoolindex) 2147 .append(enclosingMethodAttribute.getMethodNameAndTypeIndex()) 2148 .append(" ")//$NON-NLS-1$ 2149 .append(enclosingMethodAttribute.getEnclosingClass()); 2150 if (enclosingMethodAttribute.getMethodNameAndTypeIndex() != 0) { 2151 buffer 2152 .append(".")//$NON-NLS-1$ 2153 .append(enclosingMethodAttribute.getMethodName()) 2154 .append(enclosingMethodAttribute.getMethodDescriptor()); 2155 } 2156 } 2157 disassembleEnumConstants(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, char[][] argumentTypes, int mode)2158 private void disassembleEnumConstants(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, char[][] argumentTypes, int mode) { 2159 writeNewLine(buffer, lineSeparator, tabNumber); 2160 final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS); 2161 final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS); 2162 // disassemble compact version of annotations 2163 if (runtimeInvisibleAnnotationsAttribute != null) { 2164 disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 2165 writeNewLine(buffer, lineSeparator, tabNumber); 2166 } 2167 if (runtimeVisibleAnnotationsAttribute != null) { 2168 disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 2169 writeNewLine(buffer, lineSeparator, tabNumber); 2170 } 2171 buffer.append(new String(fieldInfo.getName())); 2172 buffer.append('('); 2173 final int length = argumentTypes.length; 2174 if (length != 0) { 2175 // insert default value for corresponding argument types 2176 for (int i = 0; i < length; i++) { 2177 if (i != 0) { 2178 buffer.append(Messages.disassembler_comma); 2179 } 2180 final char[] type = argumentTypes[i]; 2181 switch(type.length) { 2182 case 1 : 2183 switch(type[0]) { 2184 case 'B' : 2185 case 'I' : 2186 case 'J' : 2187 case 'D' : 2188 case 'F' : 2189 case 'S' : 2190 buffer.append('0'); 2191 break; 2192 case 'Z' : 2193 buffer.append("false"); //$NON-NLS-1$ 2194 break; 2195 case 'C' : 2196 buffer.append("\' \'"); //$NON-NLS-1$ 2197 break; 2198 } 2199 break; 2200 default : 2201 buffer.append("null"); //$NON-NLS-1$ 2202 } 2203 } 2204 } 2205 buffer.append(')').append(Messages.disassembler_comma); 2206 } 2207 2208 /** 2209 * Disassemble a field info 2210 */ disassemble(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2211 private void disassemble(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 2212 writeNewLine(buffer, lineSeparator, tabNumber); 2213 final char[] fieldDescriptor = fieldInfo.getDescriptor(); 2214 final ISignatureAttribute signatureAttribute = (ISignatureAttribute) Util.getAttribute(fieldInfo, IAttributeNamesConstants.SIGNATURE); 2215 if (checkMode(mode, SYSTEM | DETAILED)) { 2216 buffer.append(Messages.bind(Messages.classfileformat_fieldddescriptor, 2217 new String[] { 2218 Integer.toString(fieldInfo.getDescriptorIndex()), 2219 new String(fieldDescriptor) 2220 })); 2221 if (fieldInfo.isDeprecated()) { 2222 buffer.append(Messages.disassembler_deprecated); 2223 } 2224 writeNewLine(buffer, lineSeparator, tabNumber); 2225 if (signatureAttribute != null) { 2226 buffer.append(Messages.bind(Messages.disassembler_signatureattributeheader, new String(signatureAttribute.getSignature()))); 2227 writeNewLine(buffer, lineSeparator, tabNumber); 2228 } 2229 } 2230 final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS); 2231 final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS); 2232 final IClassFileAttribute runtimeVisibleTypeAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS); 2233 final IClassFileAttribute runtimeInvisibleTypeAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS); 2234 if (checkMode(mode, DETAILED)) { 2235 // disassemble compact version of annotations 2236 if (runtimeInvisibleAnnotationsAttribute != null) { 2237 disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 2238 writeNewLine(buffer, lineSeparator, tabNumber); 2239 } 2240 if (runtimeVisibleAnnotationsAttribute != null) { 2241 disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 2242 writeNewLine(buffer, lineSeparator, tabNumber); 2243 } 2244 } 2245 if (checkMode(mode, WORKING_COPY)) { 2246 decodeModifiersForFieldForWorkingCopy(buffer, fieldInfo.getAccessFlags()); 2247 if (signatureAttribute != null) { 2248 buffer.append(returnClassName(getSignatureForField(signatureAttribute.getSignature()), '.', mode)); 2249 } else { 2250 buffer.append(returnClassName(getSignatureForField(fieldDescriptor), '.', mode)); 2251 } 2252 } else { 2253 decodeModifiersForField(buffer, fieldInfo.getAccessFlags()); 2254 if (fieldInfo.isSynthetic()) { 2255 buffer.append("synthetic"); //$NON-NLS-1$ 2256 buffer.append(Messages.disassembler_space); 2257 } 2258 buffer.append(returnClassName(getSignatureForField(fieldDescriptor), '.', mode)); 2259 } 2260 buffer.append(' '); 2261 buffer.append(new String(fieldInfo.getName())); 2262 IConstantValueAttribute constantValueAttribute = fieldInfo.getConstantValueAttribute(); 2263 if (constantValueAttribute != null) { 2264 buffer.append(Messages.disassembler_fieldhasconstant); 2265 IConstantPoolEntry constantPoolEntry = constantValueAttribute.getConstantValue(); 2266 switch(constantPoolEntry.getKind()) { 2267 case IConstantPoolConstant.CONSTANT_Long : 2268 buffer.append(constantPoolEntry.getLongValue() + "L"); //$NON-NLS-1$ 2269 break; 2270 case IConstantPoolConstant.CONSTANT_Float : 2271 buffer.append(constantPoolEntry.getFloatValue() + "f"); //$NON-NLS-1$ 2272 break; 2273 case IConstantPoolConstant.CONSTANT_Double : 2274 final double doubleValue = constantPoolEntry.getDoubleValue(); 2275 if (checkMode(mode, ClassFileBytesDisassembler.WORKING_COPY)) { 2276 if (doubleValue == Double.POSITIVE_INFINITY) { 2277 buffer.append("1.0 / 0.0"); //$NON-NLS-1$ 2278 } else if (doubleValue == Double.NEGATIVE_INFINITY) { 2279 buffer.append("-1.0 / 0.0"); //$NON-NLS-1$ 2280 } else { 2281 buffer.append(constantPoolEntry.getDoubleValue()); 2282 } 2283 } else { 2284 buffer.append(constantPoolEntry.getDoubleValue()); 2285 } 2286 break; 2287 case IConstantPoolConstant.CONSTANT_Integer: 2288 switch(fieldDescriptor[0]) { 2289 case 'C' : 2290 buffer.append("'" + (char) constantPoolEntry.getIntegerValue() + "'"); //$NON-NLS-1$//$NON-NLS-2$ 2291 break; 2292 case 'Z' : 2293 buffer.append(constantPoolEntry.getIntegerValue() == 1 ? "true" : "false");//$NON-NLS-1$//$NON-NLS-2$ 2294 break; 2295 case 'B' : 2296 buffer.append(constantPoolEntry.getIntegerValue()); 2297 break; 2298 case 'S' : 2299 buffer.append(constantPoolEntry.getIntegerValue()); 2300 break; 2301 case 'I' : 2302 buffer.append(constantPoolEntry.getIntegerValue()); 2303 } 2304 break; 2305 case IConstantPoolConstant.CONSTANT_String: 2306 buffer.append("\"" + decodeStringValue(constantPoolEntry.getStringValue()) + "\"" );//$NON-NLS-1$//$NON-NLS-2$ 2307 } 2308 } 2309 buffer.append(Messages.disassembler_endoffieldheader); 2310 if (checkMode(mode, SYSTEM)) { 2311 IClassFileAttribute[] attributes = fieldInfo.getAttributes(); 2312 int length = attributes.length; 2313 if (length != 0) { 2314 for (int i = 0; i < length; i++) { 2315 IClassFileAttribute attribute = attributes[i]; 2316 if (attribute != constantValueAttribute 2317 && attribute != signatureAttribute 2318 && attribute != runtimeInvisibleAnnotationsAttribute 2319 && attribute != runtimeVisibleAnnotationsAttribute 2320 && attribute != runtimeInvisibleTypeAnnotationsAttribute 2321 && attribute != runtimeVisibleTypeAnnotationsAttribute 2322 && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED) 2323 && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) { 2324 disassemble(attribute, buffer, lineSeparator, tabNumber, mode); 2325 } 2326 } 2327 } 2328 if (runtimeVisibleAnnotationsAttribute != null) { 2329 disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 2330 } 2331 if (runtimeInvisibleAnnotationsAttribute != null) { 2332 disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 2333 } 2334 if (runtimeVisibleTypeAnnotationsAttribute != null) { 2335 disassemble((IRuntimeVisibleTypeAnnotationsAttribute) runtimeVisibleTypeAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 2336 } 2337 if (runtimeInvisibleTypeAnnotationsAttribute != null) { 2338 disassemble((IRuntimeInvisibleTypeAnnotationsAttribute) runtimeInvisibleTypeAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode); 2339 } 2340 } 2341 } 2342 disassemble(IInnerClassesAttribute innerClassesAttribute, StringBuffer buffer, String lineSeparator, int tabNumber)2343 private void disassemble(IInnerClassesAttribute innerClassesAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { 2344 writeNewLine(buffer, lineSeparator, tabNumber); 2345 buffer.append(Messages.disassembler_innerattributesheader); 2346 writeNewLine(buffer, lineSeparator, tabNumber + 1); 2347 IInnerClassesAttributeEntry[] innerClassesAttributeEntries = innerClassesAttribute.getInnerClassAttributesEntries(); 2348 int length = innerClassesAttributeEntries.length; 2349 int innerClassNameIndex, outerClassNameIndex, innerNameIndex, accessFlags; 2350 IInnerClassesAttributeEntry innerClassesAttributeEntry; 2351 for (int i = 0; i < length; i++) { 2352 if (i != 0) { 2353 buffer.append(Messages.disassembler_comma); 2354 writeNewLine(buffer, lineSeparator, tabNumber + 1); 2355 } 2356 innerClassesAttributeEntry = innerClassesAttributeEntries[i]; 2357 innerClassNameIndex = innerClassesAttributeEntry.getInnerClassNameIndex(); 2358 outerClassNameIndex = innerClassesAttributeEntry.getOuterClassNameIndex(); 2359 innerNameIndex = innerClassesAttributeEntry.getInnerNameIndex(); 2360 accessFlags = innerClassesAttributeEntry.getAccessFlags(); 2361 buffer 2362 .append(Messages.disassembler_openinnerclassentry) 2363 .append(Messages.disassembler_inner_class_info_name) 2364 .append(Messages.disassembler_constantpoolindex) 2365 .append(innerClassNameIndex); 2366 if (innerClassNameIndex != 0) { 2367 buffer 2368 .append(Messages.disassembler_space) 2369 .append(innerClassesAttributeEntry.getInnerClassName()); 2370 } 2371 buffer 2372 .append(Messages.disassembler_comma) 2373 .append(Messages.disassembler_space) 2374 .append(Messages.disassembler_outer_class_info_name) 2375 .append(Messages.disassembler_constantpoolindex) 2376 .append(outerClassNameIndex); 2377 if (outerClassNameIndex != 0) { 2378 buffer 2379 .append(Messages.disassembler_space) 2380 .append(innerClassesAttributeEntry.getOuterClassName()); 2381 } 2382 writeNewLine(buffer, lineSeparator, tabNumber); 2383 dumpTab(tabNumber, buffer); 2384 buffer.append(Messages.disassembler_space); 2385 buffer 2386 .append(Messages.disassembler_inner_name) 2387 .append(Messages.disassembler_constantpoolindex) 2388 .append(innerNameIndex); 2389 if (innerNameIndex != 0) { 2390 buffer 2391 .append(Messages.disassembler_space) 2392 .append(innerClassesAttributeEntry.getInnerName()); 2393 } 2394 buffer 2395 .append(Messages.disassembler_comma) 2396 .append(Messages.disassembler_space) 2397 .append(Messages.disassembler_inner_accessflags) 2398 .append(accessFlags) 2399 .append(Messages.disassembler_space); 2400 decodeModifiersForInnerClasses(buffer, accessFlags, true); 2401 buffer 2402 .append(Messages.disassembler_closeinnerclassentry); 2403 } 2404 } 2405 disassemble(IBootstrapMethodsAttribute bootstrapMethodsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, IConstantPool constantPool)2406 private void disassemble(IBootstrapMethodsAttribute bootstrapMethodsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, IConstantPool constantPool) { 2407 writeNewLine(buffer, lineSeparator, tabNumber); 2408 buffer.append(Messages.disassembler_bootstrapmethodattributesheader); 2409 writeNewLine(buffer, lineSeparator, tabNumber + 1); 2410 IBootstrapMethodsEntry[] entries = bootstrapMethodsAttribute.getBootstrapMethods(); 2411 int length = entries.length; 2412 for (int i = 0; i < length; i++) { 2413 if (i != 0) { 2414 buffer.append(Messages.disassembler_comma); 2415 writeNewLine(buffer, lineSeparator, tabNumber + 1); 2416 } 2417 IBootstrapMethodsEntry entry = entries[i]; 2418 String[] argumentsName = bootstrapArgumentsDescription(entry, constantPool); 2419 2420 buffer.append( 2421 Messages.bind( 2422 Messages.disassembler_bootstrapmethodentry, 2423 new String[] { 2424 Integer.toString(i), 2425 Integer.toString(entry.getBootstrapMethodReference()), 2426 bootstrapMethodDescription(entry, constantPool), 2427 getArguments(entry.getBootstrapArguments(), argumentsName) 2428 })); 2429 } 2430 } 2431 getArguments(int[] arguments, String[] argumentsName)2432 private String getArguments(int[] arguments, String[] argumentsName) { 2433 StringBuffer buffer = new StringBuffer(); 2434 for (int i = 0, max = arguments.length; i < max; i++) { 2435 buffer.append( 2436 Messages.bind( 2437 Messages.disassembler_bootstrapmethodentry_argument, 2438 new String[] { 2439 Integer.toString(arguments[i]), 2440 argumentsName[i] 2441 })); 2442 if (i != arguments.length - 1) 2443 buffer.append("\n\t\t"); //$NON-NLS-1$ 2444 } 2445 return String.valueOf(buffer); 2446 } disassemble(int index, IParameterAnnotation parameterAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2447 private void disassemble(int index, IParameterAnnotation parameterAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 2448 IAnnotation[] annotations = parameterAnnotation.getAnnotations(); 2449 writeNewLine(buffer, lineSeparator, tabNumber + 1); 2450 buffer.append( 2451 Messages.bind(Messages.disassembler_parameterannotationentrystart, new String[] {Integer.toString(index), Integer.toString(annotations.length)})); 2452 for (int i = 0, max = annotations.length; i < max; i++) { 2453 disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1, mode); 2454 } 2455 } 2456 disassemble(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2457 private void disassemble(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 2458 writeNewLine(buffer, lineSeparator, tabNumber + 1); 2459 buffer.append(Messages.disassembler_runtimeinvisibleannotationsattributeheader); 2460 IAnnotation[] annotations = runtimeInvisibleAnnotationsAttribute.getAnnotations(); 2461 for (int i = 0, max = annotations.length; i < max; i++) { 2462 disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1, mode); 2463 } 2464 } 2465 disassemble(IRuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2466 private void disassemble(IRuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 2467 writeNewLine(buffer, lineSeparator, tabNumber + 1); 2468 buffer.append(Messages.disassembler_runtimeinvisibleparameterannotationsattributeheader); 2469 IParameterAnnotation[] parameterAnnotations = runtimeInvisibleParameterAnnotationsAttribute.getParameterAnnotations(); 2470 for (int i = 0, max = parameterAnnotations.length; i < max; i++) { 2471 disassemble(i, parameterAnnotations[i], buffer, lineSeparator, tabNumber + 1, mode); 2472 } 2473 } 2474 disassemble(IRuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2475 private void disassemble(IRuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 2476 writeNewLine(buffer, lineSeparator, tabNumber + 1); 2477 buffer.append(Messages.disassembler_runtimeinvisibletypeannotationsattributeheader); 2478 IExtendedAnnotation[] extendedAnnotations = runtimeInvisibleTypeAnnotationsAttribute.getExtendedAnnotations(); 2479 for (int i = 0, max = extendedAnnotations.length; i < max; i++) { 2480 disassemble(extendedAnnotations[i], buffer, lineSeparator, tabNumber + 1, mode); 2481 } 2482 } 2483 disassemble(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2484 private void disassemble(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 2485 writeNewLine(buffer, lineSeparator, tabNumber + 1); 2486 buffer.append(Messages.disassembler_runtimevisibleannotationsattributeheader); 2487 IAnnotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations(); 2488 for (int i = 0, max = annotations.length; i < max; i++) { 2489 disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1, mode); 2490 } 2491 } 2492 disassemble(IRuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2493 private void disassemble(IRuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 2494 writeNewLine(buffer, lineSeparator, tabNumber + 1); 2495 buffer.append(Messages.disassembler_runtimevisibleparameterannotationsattributeheader); 2496 IParameterAnnotation[] parameterAnnotations = runtimeVisibleParameterAnnotationsAttribute.getParameterAnnotations(); 2497 for (int i = 0, max = parameterAnnotations.length; i < max; i++) { 2498 disassemble(i, parameterAnnotations[i], buffer, lineSeparator, tabNumber + 1, mode); 2499 } 2500 } 2501 disassemble(IRuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2502 private void disassemble(IRuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 2503 writeNewLine(buffer, lineSeparator, tabNumber + 1); 2504 buffer.append(Messages.disassembler_runtimevisibletypeannotationsattributeheader); 2505 IExtendedAnnotation[] extendedAnnotations = runtimeVisibleTypeAnnotationsAttribute.getExtendedAnnotations(); 2506 for (int i = 0, max = extendedAnnotations.length; i < max; i++) { 2507 disassemble(extendedAnnotations[i], buffer, lineSeparator, tabNumber + 1, mode); 2508 } 2509 } 2510 disassemble(IVerificationTypeInfo[] infos, int mode)2511 private String disassemble(IVerificationTypeInfo[] infos, int mode) { 2512 StringBuffer buffer = new StringBuffer(); 2513 buffer.append('{'); 2514 for (int i = 0, max = infos.length; i < max; i++) { 2515 if(i != 0) { 2516 buffer 2517 .append(Messages.disassembler_comma) 2518 .append(Messages.disassembler_space); 2519 } 2520 switch(infos[i].getTag()) { 2521 case IVerificationTypeInfo.ITEM_DOUBLE : 2522 buffer.append("double"); //$NON-NLS-1$ 2523 break; 2524 case IVerificationTypeInfo.ITEM_FLOAT : 2525 buffer.append("float"); //$NON-NLS-1$ 2526 break; 2527 case IVerificationTypeInfo.ITEM_INTEGER : 2528 buffer.append("int"); //$NON-NLS-1$ 2529 break; 2530 case IVerificationTypeInfo.ITEM_LONG : 2531 buffer.append("long"); //$NON-NLS-1$ 2532 break; 2533 case IVerificationTypeInfo.ITEM_NULL : 2534 buffer.append("null"); //$NON-NLS-1$ 2535 break; 2536 case IVerificationTypeInfo.ITEM_OBJECT : 2537 char[] classTypeName = infos[i].getClassTypeName(); 2538 CharOperation.replace(classTypeName, '/', '.'); 2539 if (classTypeName.length > 0 && classTypeName[0] == '[') { // length check for resilience 2540 classTypeName = Signature.toCharArray(classTypeName); 2541 } 2542 buffer.append(returnClassName(classTypeName, '.', mode)); 2543 break; 2544 case IVerificationTypeInfo.ITEM_TOP : 2545 buffer.append("_"); //$NON-NLS-1$ 2546 break; 2547 case IVerificationTypeInfo.ITEM_UNINITIALIZED : 2548 buffer.append("uninitialized("); //$NON-NLS-1$ 2549 buffer.append(infos[i].getOffset()); 2550 buffer.append(')'); 2551 break; 2552 case IVerificationTypeInfo.ITEM_UNINITIALIZED_THIS : 2553 buffer.append("uninitialized_this"); //$NON-NLS-1$ 2554 } 2555 } 2556 buffer.append('}'); 2557 return String.valueOf(buffer); 2558 } 2559 disassembleAsModifier(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2560 private void disassembleAsModifier(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 2561 final char[] typeName = CharOperation.replaceOnCopy(annotation.getTypeName(), '/', '.'); 2562 buffer.append('@').append(returnClassName(Signature.toCharArray(typeName), '.', mode)); 2563 final IAnnotationComponent[] components = annotation.getComponents(); 2564 final int length = components.length; 2565 if (length != 0) { 2566 buffer.append('('); 2567 for (int i = 0; i < length; i++) { 2568 if (i > 0) { 2569 buffer.append(','); 2570 writeNewLine(buffer, lineSeparator, tabNumber); 2571 } 2572 disassembleAsModifier(components[i], buffer, lineSeparator, tabNumber + 1, mode); 2573 } 2574 buffer.append(')'); 2575 } 2576 } 2577 disassembleAsModifier(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2578 private void disassembleAsModifier(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 2579 buffer.append(annotationComponent.getComponentName()).append('='); 2580 disassembleAsModifier(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1, mode); 2581 } 2582 disassembleAsModifier(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2583 private void disassembleAsModifier(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 2584 switch(annotationComponentValue.getTag()) { 2585 case IAnnotationComponentValue.BYTE_TAG: 2586 case IAnnotationComponentValue.CHAR_TAG: 2587 case IAnnotationComponentValue.DOUBLE_TAG: 2588 case IAnnotationComponentValue.FLOAT_TAG: 2589 case IAnnotationComponentValue.INTEGER_TAG: 2590 case IAnnotationComponentValue.LONG_TAG: 2591 case IAnnotationComponentValue.SHORT_TAG: 2592 case IAnnotationComponentValue.BOOLEAN_TAG: 2593 case IAnnotationComponentValue.STRING_TAG: 2594 IConstantPoolEntry constantPoolEntry = annotationComponentValue.getConstantValue(); 2595 String value = null; 2596 switch(constantPoolEntry.getKind()) { 2597 case IConstantPoolConstant.CONSTANT_Long : 2598 value = constantPoolEntry.getLongValue() + "L"; //$NON-NLS-1$ 2599 break; 2600 case IConstantPoolConstant.CONSTANT_Float : 2601 value = constantPoolEntry.getFloatValue() + "f"; //$NON-NLS-1$ 2602 break; 2603 case IConstantPoolConstant.CONSTANT_Double : 2604 value = Double.toString(constantPoolEntry.getDoubleValue()); 2605 break; 2606 case IConstantPoolConstant.CONSTANT_Integer: 2607 StringBuffer temp = new StringBuffer(); 2608 switch(annotationComponentValue.getTag()) { 2609 case IAnnotationComponentValue.CHAR_TAG : 2610 temp.append('\''); 2611 escapeChar(temp, (char) constantPoolEntry.getIntegerValue()); 2612 temp.append('\''); 2613 break; 2614 case IAnnotationComponentValue.BOOLEAN_TAG : 2615 temp.append(constantPoolEntry.getIntegerValue() == 1 ? "true" : "false");//$NON-NLS-1$//$NON-NLS-2$ 2616 break; 2617 case IAnnotationComponentValue.BYTE_TAG : 2618 temp.append("(byte) ").append(constantPoolEntry.getIntegerValue()); //$NON-NLS-1$ 2619 break; 2620 case IAnnotationComponentValue.SHORT_TAG : 2621 temp.append("(short) ").append(constantPoolEntry.getIntegerValue()); //$NON-NLS-1$ 2622 break; 2623 case IAnnotationComponentValue.INTEGER_TAG : 2624 temp.append("(int) ").append(constantPoolEntry.getIntegerValue()); //$NON-NLS-1$ 2625 } 2626 value = String.valueOf(temp); 2627 break; 2628 case IConstantPoolConstant.CONSTANT_Utf8: 2629 value = "\"" + decodeStringValue(constantPoolEntry.getUtf8Value()) + "\"";//$NON-NLS-1$//$NON-NLS-2$ 2630 } 2631 buffer.append(value); 2632 break; 2633 case IAnnotationComponentValue.ENUM_TAG: 2634 final char[] typeName = CharOperation.replaceOnCopy(annotationComponentValue.getEnumConstantTypeName(), '/', '.'); 2635 final char[] constantName = annotationComponentValue.getEnumConstantName(); 2636 buffer.append(returnClassName(Signature.toCharArray(typeName), '.', mode)).append('.').append(constantName); 2637 break; 2638 case IAnnotationComponentValue.CLASS_TAG: 2639 constantPoolEntry = annotationComponentValue.getClassInfo(); 2640 final char[] className = CharOperation.replaceOnCopy(constantPoolEntry.getUtf8Value(), '/', '.'); 2641 buffer.append(returnClassName(Signature.toCharArray(className), '.', mode)); 2642 break; 2643 case IAnnotationComponentValue.ANNOTATION_TAG: 2644 IAnnotation annotation = annotationComponentValue.getAnnotationValue(); 2645 disassembleAsModifier(annotation, buffer, lineSeparator, tabNumber + 1, mode); 2646 break; 2647 case IAnnotationComponentValue.ARRAY_TAG: 2648 final IAnnotationComponentValue[] annotationComponentValues = annotationComponentValue.getAnnotationComponentValues(); 2649 buffer.append('{'); 2650 for (int i = 0, max = annotationComponentValues.length; i < max; i++) { 2651 if (i > 0) { 2652 buffer.append(','); 2653 } 2654 disassembleAsModifier(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1, mode); 2655 } 2656 buffer.append('}'); 2657 } 2658 } 2659 disassembleAsModifier(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2660 private void disassembleAsModifier(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 2661 IAnnotationComponentValue componentValue = annotationDefaultAttribute.getMemberValue(); 2662 disassembleAsModifier(componentValue, buffer, lineSeparator, tabNumber + 1, mode); 2663 } 2664 disassembleAsModifier(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2665 private void disassembleAsModifier(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 2666 IAnnotation[] annotations = runtimeInvisibleAnnotationsAttribute.getAnnotations(); 2667 for (int i = 0, max = annotations.length; i < max; i++) { 2668 disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode); 2669 } 2670 } 2671 disassembleAsModifier(IParameterAnnotation[] parameterAnnotations, StringBuffer buffer, int index, String lineSeparator, int tabNumber, int mode)2672 private void disassembleAsModifier(IParameterAnnotation[] parameterAnnotations, StringBuffer buffer, int index, String lineSeparator, int tabNumber, int mode) { 2673 if (parameterAnnotations.length > index) { 2674 disassembleAsModifier(parameterAnnotations[index], buffer, lineSeparator, tabNumber + 1, mode); 2675 } 2676 } 2677 disassembleAsModifier(IParameterAnnotation parameterAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2678 private void disassembleAsModifier(IParameterAnnotation parameterAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 2679 if (parameterAnnotation == null) return; 2680 IAnnotation[] annotations = parameterAnnotation.getAnnotations(); 2681 for (int i = 0, max = annotations.length; i < max; i++) { 2682 if (i > 0) { 2683 buffer.append(' '); 2684 } 2685 disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode); 2686 } 2687 } 2688 disassembleAsModifier(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2689 private void disassembleAsModifier(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 2690 IAnnotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations(); 2691 for (int i = 0, max = annotations.length; i < max; i++) { 2692 if (i > 0) { 2693 writeNewLine(buffer, lineSeparator, tabNumber); 2694 } 2695 disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode); 2696 } 2697 } 2698 disassembleTypeMembers(IClassFileReader classFileReader, char[] className, StringBuffer buffer, String lineSeparator, int tabNumber, int mode, boolean isEnum)2699 private void disassembleTypeMembers(IClassFileReader classFileReader, char[] className, StringBuffer buffer, String lineSeparator, int tabNumber, int mode, boolean isEnum) { 2700 IFieldInfo[] fields = classFileReader.getFieldInfos(); 2701 if (isEnum && checkMode(mode, WORKING_COPY)) { 2702 int index = 0; 2703 final int fieldsLength = fields.length; 2704 IMethodInfo[] methods = classFileReader.getMethodInfos(); 2705 char[][] constructorArguments = getConstructorArgumentsForEnum(methods); 2706 enumConstantLoop: for (; index < fieldsLength; index++) { 2707 final IFieldInfo fieldInfo = fields[index]; 2708 final int accessFlags = fieldInfo.getAccessFlags(); 2709 if ((accessFlags & IModifierConstants.ACC_ENUM) != 0) { 2710 writeNewLine(buffer, lineSeparator, tabNumber); 2711 disassembleEnumConstants(fields[index], buffer, lineSeparator, tabNumber, constructorArguments, mode); 2712 } else { 2713 break enumConstantLoop; 2714 } 2715 } 2716 buffer.append(';'); 2717 boolean foundSyntheticField = false; 2718 fieldLoop: for (; index < fieldsLength; index++) { 2719 if (!foundSyntheticField && CharOperation.equals(TypeConstants.SYNTHETIC_ENUM_VALUES, fields[index].getName())) { 2720 foundSyntheticField = true; 2721 continue fieldLoop; 2722 } 2723 writeNewLine(buffer, lineSeparator, tabNumber); 2724 disassemble(fields[index], buffer, lineSeparator, tabNumber, mode); 2725 } 2726 methodLoop: for (int i = 0, max = methods.length; i < max; i++) { 2727 final IMethodInfo methodInfo = methods[i]; 2728 if (CharOperation.equals(methodInfo.getName(), TypeConstants.VALUES)) { 2729 final char[] descriptor = methodInfo.getDescriptor(); 2730 CharOperation.replace(descriptor, '/', '.'); 2731 if (Signature.getParameterCount(descriptor) == 0) { 2732 if (CharOperation.equals(returnClassName(Signature.getReturnType(descriptor), '.', mode), 2733 CharOperation.concat(new char[] {'[', 'L'}, className, new char[] {';'}))) { 2734 continue methodLoop; 2735 } 2736 } 2737 } else if (CharOperation.equals(methodInfo.getName(), TypeConstants.VALUEOF)) { 2738 final char[] descriptor = methodInfo.getDescriptor(); 2739 CharOperation.replace(descriptor, '/', '.'); 2740 final char[][] parameterTypes = Signature.getParameterTypes(descriptor); 2741 if (parameterTypes.length == 1 2742 && CharOperation.equals(parameterTypes[0], "Ljava.lang.String;".toCharArray())) { //$NON-NLS-1$ 2743 if (CharOperation.equals(returnClassName(Signature.getReturnType(descriptor), '.', mode), 2744 CharOperation.concat('L', className, ';'))) { 2745 continue methodLoop; 2746 } 2747 } 2748 } else if (methodInfo.isClinit() || methodInfo.isSynthetic()) { 2749 continue methodLoop; 2750 } else if (methodInfo.isConstructor()) { 2751 writeNewLine(buffer, lineSeparator, tabNumber); 2752 disassembleEnumConstructor(classFileReader, className, methodInfo, buffer, lineSeparator, tabNumber, mode); 2753 } else { 2754 writeNewLine(buffer, lineSeparator, tabNumber); 2755 disassemble(classFileReader, className, methodInfo, buffer, lineSeparator, tabNumber, mode); 2756 } 2757 } 2758 } else { 2759 for (int i = 0, max = fields.length; i < max; i++) { 2760 writeNewLine(buffer, lineSeparator, tabNumber); 2761 disassemble(fields[i], buffer, lineSeparator, tabNumber, mode); 2762 } 2763 IMethodInfo[] methods = classFileReader.getMethodInfos(); 2764 for (int i = 0, max = methods.length; i < max; i++) { 2765 writeNewLine(buffer, lineSeparator, tabNumber); 2766 disassemble(classFileReader, className, methods[i], buffer, lineSeparator, tabNumber, mode); 2767 } 2768 } 2769 } 2770 getConstructorArgumentsForEnum(final IMethodInfo[] methods)2771 private char[][] getConstructorArgumentsForEnum(final IMethodInfo[] methods) { 2772 loop: for (int i = 0, max = methods.length; i < max; i++) { 2773 IMethodInfo methodInfo = methods[i]; 2774 if (methodInfo.isConstructor()) { 2775 char[][] parameterTypes = Signature.getParameterTypes(methodInfo.getDescriptor()); 2776 final int length = parameterTypes.length; 2777 if (length >= 2) { 2778 return CharOperation.subarray(parameterTypes, 2, length); 2779 } 2780 } else { 2781 continue loop; 2782 } 2783 } 2784 return null; 2785 } 2786 dumpTab(int tabNumber, StringBuffer buffer)2787 private final void dumpTab(int tabNumber, StringBuffer buffer) { 2788 for (int i = 0; i < tabNumber; i++) { 2789 buffer.append(Messages.disassembler_indentation); 2790 } 2791 } 2792 dumpNewLineWithTabs(String lineSeparator, int tabNumber)2793 private final String dumpNewLineWithTabs(String lineSeparator, int tabNumber) { 2794 StringBuffer buffer = new StringBuffer(); 2795 writeNewLine(buffer, lineSeparator, tabNumber); 2796 return String.valueOf(buffer); 2797 } 2798 2799 /** 2800 * @see org.eclipse.jdt.core.util.ClassFileBytesDisassembler#getDescription() 2801 */ 2802 @Override getDescription()2803 public String getDescription() { 2804 return Messages.disassembler_description; 2805 } 2806 getParameterNames(char[] methodDescriptor, ICodeAttribute codeAttribute, IMethodParametersAttribute parametersAttribute, int accessFlags)2807 private char[][] getParameterNames(char[] methodDescriptor, ICodeAttribute codeAttribute, IMethodParametersAttribute parametersAttribute, int accessFlags) { 2808 int paramCount = Signature.getParameterCount(methodDescriptor); 2809 char[][] parameterNames = new char[paramCount][]; 2810 // check if the code attribute has debug info for this method 2811 if (parametersAttribute != null) { 2812 int parameterCount = parametersAttribute.getMethodParameterLength(); 2813 for (int i = 0; i < paramCount; i++) { 2814 if (i < parameterCount && parametersAttribute.getParameterName(i) != null) { 2815 parameterNames[i] = parametersAttribute.getParameterName(i); 2816 } else { 2817 parameterNames[i] = Messages.disassembler_anonymousparametername.toCharArray(); 2818 } 2819 } 2820 } else if (codeAttribute != null) { 2821 ILocalVariableAttribute localVariableAttribute = codeAttribute.getLocalVariableAttribute(); 2822 if (localVariableAttribute != null) { 2823 ILocalVariableTableEntry[] entries = localVariableAttribute.getLocalVariableTable(); 2824 final int startingIndex = (accessFlags & IModifierConstants.ACC_STATIC) != 0 ? 0 : 1; 2825 for (int i = 0; i < paramCount; i++) { 2826 ILocalVariableTableEntry searchedEntry = getEntryFor(getLocalIndex(startingIndex, i, methodDescriptor), entries); 2827 if (searchedEntry != null) { 2828 parameterNames[i] = searchedEntry.getName(); 2829 } else { 2830 parameterNames[i] = CharOperation.concat(Messages.disassembler_parametername.toCharArray(), Integer.toString(i).toCharArray()); 2831 } 2832 } 2833 } else { 2834 for (int i = 0; i < paramCount; i++) { 2835 parameterNames[i] = CharOperation.concat(Messages.disassembler_parametername.toCharArray(), Integer.toString(i).toCharArray()); 2836 } 2837 } 2838 } else { 2839 for (int i = 0; i < paramCount; i++) { 2840 parameterNames[i] = CharOperation.concat(Messages.disassembler_parametername.toCharArray(), Integer.toString(i).toCharArray()); 2841 } 2842 } 2843 return parameterNames; 2844 } 2845 getLocalIndex(final int startingSlot, final int index, final char[] methodDescriptor)2846 private int getLocalIndex(final int startingSlot, final int index, final char[] methodDescriptor) { 2847 int slot = startingSlot; 2848 final char[][] types = Signature.getParameterTypes(methodDescriptor); 2849 for (int i = 0; i < index; i++) { 2850 final char[] type = types[i]; 2851 switch(type.length) { 2852 case 1 : 2853 switch(type[0]) { 2854 case 'D' : 2855 case 'J' : 2856 slot += 2; 2857 break; 2858 default : 2859 slot++; 2860 } 2861 break; 2862 default : 2863 slot++; 2864 } 2865 } 2866 return slot; 2867 } 2868 getEntryFor(final int index, final ILocalVariableTableEntry[] entries)2869 private ILocalVariableTableEntry getEntryFor(final int index, final ILocalVariableTableEntry[] entries) { 2870 for (int i = 0, max = entries.length; i < max; i++) { 2871 ILocalVariableTableEntry entry = entries[i]; 2872 if (index == entry.getIndex()) { 2873 return entry; 2874 } 2875 } 2876 return null; 2877 } 2878 getSignatureForField(char[] fieldDescriptor)2879 private char[] getSignatureForField(char[] fieldDescriptor) { 2880 char[] newFieldDescriptor = CharOperation.replaceOnCopy(fieldDescriptor, '/', '.'); 2881 newFieldDescriptor = CharOperation.replaceOnCopy(newFieldDescriptor, '$', '%'); 2882 char[] fieldDescriptorSignature = Signature.toCharArray(newFieldDescriptor); 2883 CharOperation.replace(fieldDescriptorSignature, '%', '$'); 2884 return fieldDescriptorSignature; 2885 } getSignatureForComponent(char[] componentDescriptor)2886 private char[] getSignatureForComponent(char[] componentDescriptor) { 2887 char[] newComponentDescriptor = CharOperation.replaceOnCopy(componentDescriptor, '/', '.'); 2888 newComponentDescriptor = CharOperation.replaceOnCopy(newComponentDescriptor, '$', '%'); 2889 char[] componentDescriptorSignature = Signature.toCharArray(newComponentDescriptor); 2890 CharOperation.replace(componentDescriptorSignature, '%', '$'); 2891 return componentDescriptorSignature; 2892 } 2893 isDeprecated(IClassFileReader classFileReader)2894 private boolean isDeprecated(IClassFileReader classFileReader) { 2895 IClassFileAttribute[] attributes = classFileReader.getAttributes(); 2896 for (int i = 0, max = attributes.length; i < max; i++) { 2897 if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.DEPRECATED)) { 2898 return true; 2899 } 2900 } 2901 return false; 2902 } 2903 isSynthetic(IClassFileReader classFileReader)2904 private boolean isSynthetic(IClassFileReader classFileReader) { 2905 int flags = classFileReader.getAccessFlags(); 2906 if ((flags & IModifierConstants.ACC_SYNTHETIC) != 0) { 2907 return true; 2908 } 2909 IClassFileAttribute[] attributes = classFileReader.getAttributes(); 2910 for (int i = 0, max = attributes.length; i < max; i++) { 2911 if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) { 2912 return true; 2913 } 2914 } 2915 return false; 2916 } 2917 checkMode(int mode, int flag)2918 private boolean checkMode(int mode, int flag) { 2919 return (mode & flag) != 0; 2920 } 2921 isCompact(int mode)2922 private boolean isCompact(int mode) { 2923 return (mode & ClassFileBytesDisassembler.COMPACT) != 0; 2924 } 2925 returnClassName(char[] classInfoName, char separator, int mode)2926 private char[] returnClassName(char[] classInfoName, char separator, int mode) { 2927 if (classInfoName.length == 0) { 2928 return CharOperation.NO_CHAR; 2929 } else if (isCompact(mode)) { 2930 int lastIndexOfSlash = CharOperation.lastIndexOf(separator, classInfoName); 2931 if (lastIndexOfSlash != -1) { 2932 return CharOperation.subarray(classInfoName, lastIndexOfSlash + 1, classInfoName.length); 2933 } 2934 } 2935 return classInfoName; 2936 } 2937 writeNewLine(StringBuffer buffer, String lineSeparator, int tabNumber)2938 private void writeNewLine(StringBuffer buffer, String lineSeparator, int tabNumber) { 2939 buffer.append(lineSeparator); 2940 dumpTab(tabNumber, buffer); 2941 } 2942 toTypePathString(int[][] typepath)2943 private String toTypePathString(int[][] typepath) { 2944 StringBuffer buffer = new StringBuffer(); 2945 buffer.append('['); 2946 for (int i = 0, max = typepath.length; i < max; i++) { 2947 int[] typepathElement = typepath[i]; 2948 if (i > 0) { 2949 buffer.append(',').append(' '); 2950 } 2951 switch (typepathElement[0]) { 2952 case IExtendedAnnotationConstants.TYPE_PATH_DEEPER_IN_ARRAY: 2953 buffer.append(Messages.disassembler_extendedannotation_typepath_array); 2954 break; 2955 case IExtendedAnnotationConstants.TYPE_PATH_DEEPER_IN_INNER_TYPE: 2956 buffer.append(Messages.disassembler_extendedannotation_typepath_innertype); 2957 break; 2958 case IExtendedAnnotationConstants.TYPE_PATH_ANNOTATION_ON_WILDCARD_BOUND: 2959 buffer.append(Messages.disassembler_extendedannotation_typepath_wildcard); 2960 break; 2961 case IExtendedAnnotationConstants.TYPE_PATH_TYPE_ARGUMENT_INDEX: 2962 buffer.append( 2963 Messages.bind(Messages.disassembler_extendedannotation_typepath_typeargument, 2964 new String[] { 2965 Integer.toString(typepathElement[1]) 2966 })); 2967 break; 2968 default: 2969 throw new IllegalStateException("Unrecognized type_path_kind: "+typepathElement[0]); //$NON-NLS-1$ 2970 } 2971 } 2972 buffer.append(']'); 2973 return String.valueOf(buffer); 2974 } 2975 2976 } 2977