public ClassReference14Processor() { InvocationExprent invfor = new InvocationExprent(); invfor.setName("forName"); invfor.setClassname("java/lang/Class"); invfor.setStringDescriptor("(Ljava/lang/String;)Ljava/lang/Class;"); invfor.setDescriptor(MethodDescriptor.parseDescriptor("(Ljava/lang/String;)Ljava/lang/Class;")); invfor.setStatic(true); invfor.setLstParameters( Arrays.asList(new Exprent[] {new VarExprent(0, VarType.VARTYPE_STRING, null)})); bodyexprent = new ExitExprent(ExitExprent.EXIT_RETURN, invfor, VarType.VARTYPE_CLASS, null); InvocationExprent constr = new InvocationExprent(); constr.setName("<init>"); constr.setClassname("java/lang/NoClassDefFoundError"); constr.setStringDescriptor("()V"); constr.setFunctype(InvocationExprent.TYP_INIT); constr.setDescriptor(MethodDescriptor.parseDescriptor("()V")); NewExprent newexpr = new NewExprent( new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/NoClassDefFoundError"), new ArrayList<Exprent>(), null); newexpr.setConstructor(constr); InvocationExprent invcause = new InvocationExprent(); invcause.setName("initCause"); invcause.setClassname("java/lang/NoClassDefFoundError"); invcause.setStringDescriptor("(Ljava/lang/Throwable;)Ljava/lang/Throwable;"); invcause.setDescriptor( MethodDescriptor.parseDescriptor("(Ljava/lang/Throwable;)Ljava/lang/Throwable;")); invcause.setInstance(newexpr); invcause.setLstParameters( Arrays.asList( new Exprent[] { new VarExprent( 2, new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/ClassNotFoundException"), null) })); handlerexprent = new ExitExprent(ExitExprent.EXIT_THROW, invcause, null, null); }
public static Exprent parseAnnotationElement(DataInputStream data, ConstantPool pool) throws IOException { int tag = data.readUnsignedByte(); switch (tag) { case 'e': // enum constant String className = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); String constName = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); FieldDescriptor descr = FieldDescriptor.parseDescriptor(className); return new FieldExprent(constName, descr.type.value, true, null, descr, null); case 'c': // class String descriptor = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); VarType type = FieldDescriptor.parseDescriptor(descriptor).type; String value; switch (type.type) { case CodeConstants.TYPE_OBJECT: value = type.value; break; case CodeConstants.TYPE_BYTE: value = byte.class.getName(); break; case CodeConstants.TYPE_CHAR: value = char.class.getName(); break; case CodeConstants.TYPE_DOUBLE: value = double.class.getName(); break; case CodeConstants.TYPE_FLOAT: value = float.class.getName(); break; case CodeConstants.TYPE_INT: value = int.class.getName(); break; case CodeConstants.TYPE_LONG: value = long.class.getName(); break; case CodeConstants.TYPE_SHORT: value = short.class.getName(); break; case CodeConstants.TYPE_BOOLEAN: value = boolean.class.getName(); break; case CodeConstants.TYPE_VOID: value = void.class.getName(); break; default: throw new RuntimeException("invalid class type: " + type.type); } return new ConstExprent(VarType.VARTYPE_CLASS, value, null); case '[': // array List<Exprent> elements = Collections.emptyList(); int len = data.readUnsignedShort(); if (len > 0) { elements = new ArrayList<Exprent>(len); for (int i = 0; i < len; i++) { elements.add(parseAnnotationElement(data, pool)); } } VarType newType; if (elements.isEmpty()) { newType = new VarType(CodeConstants.TYPE_OBJECT, 1, "java/lang/Object"); } else { VarType elementType = elements.get(0).getExprType(); newType = new VarType(elementType.type, 1, elementType.value); } NewExprent newExpr = new NewExprent(newType, Collections.emptyList(), null); newExpr.setDirectArrayInit(true); newExpr.setLstArrayElements(elements); return newExpr; case '@': // annotation return parseAnnotation(data, pool); default: PrimitiveConstant cn = pool.getPrimitiveConstant(data.readUnsignedShort()); switch (tag) { case 'B': return new ConstExprent(VarType.VARTYPE_BYTE, cn.value, null); case 'C': return new ConstExprent(VarType.VARTYPE_CHAR, cn.value, null); case 'D': return new ConstExprent(VarType.VARTYPE_DOUBLE, cn.value, null); case 'F': return new ConstExprent(VarType.VARTYPE_FLOAT, cn.value, null); case 'I': return new ConstExprent(VarType.VARTYPE_INT, cn.value, null); case 'J': return new ConstExprent(VarType.VARTYPE_LONG, cn.value, null); case 'S': return new ConstExprent(VarType.VARTYPE_SHORT, cn.value, null); case 'Z': return new ConstExprent(VarType.VARTYPE_BOOLEAN, cn.value, null); case 's': return new ConstExprent(VarType.VARTYPE_STRING, cn.value, null); default: throw new RuntimeException("invalid element type!"); } } }
private void fieldToJava( ClassWrapper wrapper, StructClass cl, StructField fd, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) { int start = buffer.length(); boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE); boolean isDeprecated = fd.getAttributes().containsKey("Deprecated"); boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); if (isDeprecated) { appendDeprecation(buffer, indent); } if (interceptor != null) { String oldName = interceptor.getOldName(cl.qualifiedName + " " + fd.getName() + " " + fd.getDescriptor()); appendRenameComment(buffer, oldName, MType.FIELD, indent); } if (fd.isSynthetic()) { appendComment(buffer, "synthetic field", indent); } appendAnnotations(buffer, fd, indent); buffer.appendIndent(indent); if (!isEnum) { appendModifiers(buffer, fd.getAccessFlags(), FIELD_ALLOWED, isInterface, FIELD_EXCLUDED); } VarType fieldType = new VarType(fd.getDescriptor(), false); GenericFieldDescriptor descriptor = null; if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) { StructGenericSignatureAttribute attr = (StructGenericSignatureAttribute) fd.getAttributes().getWithKey("Signature"); if (attr != null) { descriptor = GenericMain.parseFieldSignature(attr.getSignature()); } } if (!isEnum) { if (descriptor != null) { buffer.append(GenericMain.getGenericCastTypeName(descriptor.type)); } else { buffer.append(ExprProcessor.getCastTypeName(fieldType)); } buffer.append(' '); } buffer.append(fd.getName()); tracer.incrementCurrentSourceLine(buffer.countLines(start)); Exprent initializer; if (fd.hasModifier(CodeConstants.ACC_STATIC)) { initializer = wrapper .getStaticFieldInitializers() .getWithKey(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); } else { initializer = wrapper .getDynamicFieldInitializers() .getWithKey(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); } if (initializer != null) { if (isEnum && initializer.type == Exprent.EXPRENT_NEW) { NewExprent nexpr = (NewExprent) initializer; nexpr.setEnumConst(true); buffer.append(nexpr.toJava(indent, tracer)); } else { buffer.append(" = "); // FIXME: special case field initializer. Can map to more than one method (constructor) and // bytecode intruction. buffer.append(initializer.toJava(indent, tracer)); } } else if (fd.hasModifier(CodeConstants.ACC_FINAL) && fd.hasModifier(CodeConstants.ACC_STATIC)) { StructConstantValueAttribute attr = (StructConstantValueAttribute) fd.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_CONSTANT_VALUE); if (attr != null) { PrimitiveConstant constant = cl.getPool().getPrimitiveConstant(attr.getIndex()); buffer.append(" = "); buffer.append(new ConstExprent(fieldType, constant.value, null).toJava(indent, tracer)); } } if (!isEnum) { buffer.append(";").appendLineSeparator(); tracer.incrementCurrentSourceLine(); } }