Java Code Examples for org.jetbrains.java.decompiler.util.InterpreterUtil#makeUniqueKey()

The following examples show how to use org.jetbrains.java.decompiler.util.InterpreterUtil#makeUniqueKey() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: AssertProcessor.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
public static void buildAssertions(ClassNode node) {

        ClassWrapper wrapper = node.getWrapper();

        StructField field = findAssertionField(node);

        if (field != null) {

            String key = InterpreterUtil.makeUniqueKey(field.getName(), field.getDescriptor());

            boolean res = false;

            for (MethodWrapper meth : wrapper.getMethods()) {
                RootStatement root = meth.root;
                if (root != null) {
                    res |= replaceAssertions(root, wrapper.getClassStruct().qualifiedName, key);
                }
            }

            if (res) {
                // hide the helper field
                wrapper.getHiddenMembers().add(key);
            }
        }
    }
 
Example 2
Source File: AssertProcessor.java    From JByteMod-Beta with GNU General Public License v2.0 6 votes vote down vote up
public static void buildAssertions(ClassNode node) {

    ClassWrapper wrapper = node.getWrapper();

    StructField field = findAssertionField(node);

    if (field != null) {

      String key = InterpreterUtil.makeUniqueKey(field.getName(), field.getDescriptor());

      boolean res = false;

      for (MethodWrapper meth : wrapper.getMethods()) {
        RootStatement root = meth.root;
        if (root != null) {
          res |= replaceAssertions(root, wrapper.getClassStruct().qualifiedName, key);
        }
      }

      if (res) {
        // hide the helper field
        wrapper.getHiddenMembers().add(key);
      }
    }
  }
 
Example 3
Source File: ClassWriter.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
private static void addTracer(StructClass cls, StructMethod method, BytecodeMappingTracer tracer) {
    StructLineNumberTableAttribute table =
            (StructLineNumberTableAttribute) method.getAttribute(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
    tracer.setLineNumberTable(table);
    String key = InterpreterUtil.makeUniqueKey(method.getName(), method.getDescriptor());
    DecompilerContext.getBytecodeSourceMapper().addTracer(cls.qualifiedName, key, tracer);
}
 
Example 4
Source File: InitializerProcessor.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
private static void extractStaticInitializers(ClassWrapper wrapper, MethodWrapper method) {
    RootStatement root = method.root;
    StructClass cl = wrapper.getClassStruct();
    Statement firstData = Statements.findFirstData(root);
    if (firstData != null) {
        boolean inlineInitializers = cl.hasModifier(CodeConstants.ACC_INTERFACE) || cl.hasModifier(CodeConstants.ACC_ENUM);

        while (!firstData.getExprents().isEmpty()) {
            Exprent exprent = firstData.getExprents().get(0);

            boolean found = false;

            if (exprent.type == Exprent.EXPRENT_ASSIGNMENT) {
                AssignmentExprent assignExpr = (AssignmentExprent) exprent;
                if (assignExpr.getLeft().type == Exprent.EXPRENT_FIELD) {
                    FieldExprent fExpr = (FieldExprent) assignExpr.getLeft();
                    if (fExpr.isStatic() && fExpr.getClassname().equals(cl.qualifiedName) &&
                            cl.hasField(fExpr.getName(), fExpr.getDescriptor().descriptorString)) {

                        // interfaces fields should always be initialized inline
                        if (inlineInitializers || isExprentIndependent(assignExpr.getRight(), method)) {
                            String keyField = InterpreterUtil.makeUniqueKey(fExpr.getName(), fExpr.getDescriptor().descriptorString);
                            if (!wrapper.getStaticFieldInitializers().containsKey(keyField)) {
                                wrapper.getStaticFieldInitializers().addWithKey(assignExpr.getRight(), keyField);
                                firstData.getExprents().remove(0);
                                found = true;
                            }
                        }
                    }
                }
            }

            if (!found) {
                break;
            }
        }
    }
}
 
Example 5
Source File: NestedClassProcessor.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
private static String getEnclosingVarField(StructClass cl, MethodWrapper method, DirectGraph graph, int index) {
    String field = "";

    // parameter variable final
    if (method.varproc.getVarFinal(new VarVersionPair(index, 0)) == VarTypeProcessor.VAR_NON_FINAL) {
        return null;
    }

    boolean noSynthFlag = DecompilerContext.getOption(IFernflowerPreferences.SYNTHETIC_NOT_SET);

    // no loop at the begin
    DirectNode firstNode = graph.first;
    if (firstNode.preds.isEmpty()) {
        // assignment to a synthetic field?
        for (Exprent exprent : firstNode.exprents) {
            if (exprent.type == Exprent.EXPRENT_ASSIGNMENT) {
                AssignmentExprent assignExpr = (AssignmentExprent) exprent;
                if (assignExpr.getRight().type == Exprent.EXPRENT_VAR &&
                        ((VarExprent) assignExpr.getRight()).getIndex() == index &&
                        assignExpr.getLeft().type == Exprent.EXPRENT_FIELD) {
                    FieldExprent left = (FieldExprent) assignExpr.getLeft();
                    StructField fd = cl.getField(left.getName(), left.getDescriptor().descriptorString);
                    if (fd != null &&
                            cl.qualifiedName.equals(left.getClassname()) &&
                            (fd.isSynthetic() || noSynthFlag && possiblySyntheticField(fd))) {
                        // local (== not inherited) field
                        field = InterpreterUtil.makeUniqueKey(left.getName(), left.getDescriptor().descriptorString);
                        break;
                    }
                }
            }
        }
    }

    return field;
}
 
Example 6
Source File: ClassesProcessor.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
public ClassNode(String content_class_name,
                 String content_method_name,
                 String content_method_descriptor,
                 int content_method_invocation_type,
                 String lambda_class_name,
                 String lambda_method_name,
                 String lambda_method_descriptor,
                 StructClass classStruct) { // lambda class constructor
    this.type = CLASS_LAMBDA;
    this.classStruct = classStruct; // 'parent' class containing the static function

    lambdaInformation = new LambdaInformation();

    lambdaInformation.method_name = lambda_method_name;
    lambdaInformation.method_descriptor = lambda_method_descriptor;

    lambdaInformation.content_class_name = content_class_name;
    lambdaInformation.content_method_name = content_method_name;
    lambdaInformation.content_method_descriptor = content_method_descriptor;
    lambdaInformation.content_method_invocation_type = content_method_invocation_type;

    lambdaInformation.content_method_key =
            InterpreterUtil.makeUniqueKey(lambdaInformation.content_method_name, lambdaInformation.content_method_descriptor);

    anonymousClassType = new VarType(lambda_class_name, true);

    boolean is_method_reference = (content_class_name != classStruct.qualifiedName);
    if (!is_method_reference) { // content method in the same class, check synthetic flag
        StructMethod mt = classStruct.getMethod(content_method_name, content_method_descriptor);
        is_method_reference = !mt.isSynthetic(); // if not synthetic -> method reference
    }

    lambdaInformation.is_method_reference = is_method_reference;
    lambdaInformation.is_content_method_static =
            (lambdaInformation.content_method_invocation_type == CodeConstants.CONSTANT_MethodHandle_REF_invokeStatic); // FIXME: redundant?
}
 
Example 7
Source File: ClassWriter.java    From JByteMod-Beta with GNU General Public License v2.0 5 votes vote down vote up
private static void addTracer(StructClass cls, StructMethod method, BytecodeMappingTracer tracer) {
  StructLineNumberTableAttribute table = (StructLineNumberTableAttribute) method.getAttributes()
      .getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
  tracer.setLineNumberTable(table);
  String key = InterpreterUtil.makeUniqueKey(method.getName(), method.getDescriptor());
  DecompilerContext.getBytecodeSourceMapper().addTracer(cls.qualifiedName, key, tracer);
}
 
Example 8
Source File: InitializerProcessor.java    From JByteMod-Beta with GNU General Public License v2.0 5 votes vote down vote up
private static void extractStaticInitializers(ClassWrapper wrapper, MethodWrapper method) {
  RootStatement root = method.root;
  StructClass cl = wrapper.getClassStruct();
  Statement firstData = Statements.findFirstData(root);
  if (firstData != null) {
    boolean inlineInitializers = cl.hasModifier(CodeConstants.ACC_INTERFACE) || cl.hasModifier(CodeConstants.ACC_ENUM);

    while (!firstData.getExprents().isEmpty()) {
      Exprent exprent = firstData.getExprents().get(0);

      boolean found = false;

      if (exprent.type == Exprent.EXPRENT_ASSIGNMENT) {
        AssignmentExprent assignExpr = (AssignmentExprent) exprent;
        if (assignExpr.getLeft().type == Exprent.EXPRENT_FIELD) {
          FieldExprent fExpr = (FieldExprent) assignExpr.getLeft();
          if (fExpr.isStatic() && fExpr.getClassname().equals(cl.qualifiedName)
              && cl.hasField(fExpr.getName(), fExpr.getDescriptor().descriptorString)) {

            // interfaces fields should always be initialized inline
            if (inlineInitializers || isExprentIndependent(assignExpr.getRight(), method)) {
              String keyField = InterpreterUtil.makeUniqueKey(fExpr.getName(), fExpr.getDescriptor().descriptorString);
              if (!wrapper.getStaticFieldInitializers().containsKey(keyField)) {
                wrapper.getStaticFieldInitializers().addWithKey(assignExpr.getRight(), keyField);
                firstData.getExprents().remove(0);
                found = true;
              }
            }
          }
        }
      }

      if (!found) {
        break;
      }
    }
  }
}
 
Example 9
Source File: NestedClassProcessor.java    From JByteMod-Beta with GNU General Public License v2.0 5 votes vote down vote up
private static String getEnclosingVarField(StructClass cl, MethodWrapper method, DirectGraph graph, int index) {
  String field = "";

  // parameter variable final
  if (method.varproc.getVarFinal(new VarVersionPair(index, 0)) == VarTypeProcessor.VAR_NON_FINAL) {
    return null;
  }

  boolean noSynthFlag = DecompilerContext.getOption(IFernflowerPreferences.SYNTHETIC_NOT_SET);

  // no loop at the begin
  DirectNode firstNode = graph.first;
  if (firstNode.preds.isEmpty()) {
    // assignment to a synthetic field?
    for (Exprent exprent : firstNode.exprents) {
      if (exprent.type == Exprent.EXPRENT_ASSIGNMENT) {
        AssignmentExprent assignExpr = (AssignmentExprent) exprent;
        if (assignExpr.getRight().type == Exprent.EXPRENT_VAR && ((VarExprent) assignExpr.getRight()).getIndex() == index
            && assignExpr.getLeft().type == Exprent.EXPRENT_FIELD) {
          FieldExprent left = (FieldExprent) assignExpr.getLeft();
          StructField fd = cl.getField(left.getName(), left.getDescriptor().descriptorString);

          if (fd != null && cl.qualifiedName.equals(left.getClassname()) && fd.hasModifier(CodeConstants.ACC_FINAL)
              && (fd.isSynthetic() || (noSynthFlag && fd.hasModifier(CodeConstants.ACC_PRIVATE)))) {
            // local (== not inherited) field
            field = InterpreterUtil.makeUniqueKey(left.getName(), left.getDescriptor().descriptorString);
            break;
          }
        }
      }
    }
  }

  return field;
}
 
Example 10
Source File: ClassesProcessor.java    From JByteMod-Beta with GNU General Public License v2.0 5 votes vote down vote up
public ClassNode(String content_class_name, String content_method_name, String content_method_descriptor, int content_method_invocation_type,
    String lambda_class_name, String lambda_method_name, String lambda_method_descriptor, StructClass classStruct) { // lambda class constructor
  this.type = CLASS_LAMBDA;
  this.classStruct = classStruct; // 'parent' class containing the static function

  lambdaInformation = new LambdaInformation();

  lambdaInformation.class_name = lambda_class_name;
  lambdaInformation.method_name = lambda_method_name;
  lambdaInformation.method_descriptor = lambda_method_descriptor;

  lambdaInformation.content_class_name = content_class_name;
  lambdaInformation.content_method_name = content_method_name;
  lambdaInformation.content_method_descriptor = content_method_descriptor;
  lambdaInformation.content_method_invocation_type = content_method_invocation_type;

  lambdaInformation.content_method_key = InterpreterUtil.makeUniqueKey(lambdaInformation.content_method_name,
      lambdaInformation.content_method_descriptor);

  anonymousClassType = new VarType(lambda_class_name, true);

  boolean is_method_reference = (content_class_name != classStruct.qualifiedName);
  if (!is_method_reference) { // content method in the same class, check synthetic flag
    StructMethod mt = classStruct.getMethod(content_method_name, content_method_descriptor);
    is_method_reference = !mt.isSynthetic(); // if not synthetic -> method reference
  }

  lambdaInformation.is_method_reference = is_method_reference;
  lambdaInformation.is_content_method_static = (lambdaInformation.content_method_invocation_type == CodeConstants.CONSTANT_MethodHandle_REF_invokeStatic); // FIXME: redundant?
}
 
Example 11
Source File: AssertProcessor.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
private static StructField findAssertionField(ClassNode node) {

        ClassWrapper wrapper = node.getWrapper();

        boolean noSynthFlag = DecompilerContext.getOption(IFernflowerPreferences.SYNTHETIC_NOT_SET);

        for (StructField fd : wrapper.getClassStruct().getFields()) {

            String keyField = InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor());

            // initializer exists
            if (wrapper.getStaticFieldInitializers().containsKey(keyField)) {

                // access flags set
                if (fd.hasModifier(CodeConstants.ACC_STATIC) && fd.hasModifier(CodeConstants.ACC_FINAL) && (noSynthFlag || fd.isSynthetic())) {

                    // field type boolean
                    FieldDescriptor fdescr = FieldDescriptor.parseDescriptor(fd.getDescriptor());
                    if (VarType.VARTYPE_BOOLEAN.equals(fdescr.type)) {

                        Exprent initializer = wrapper.getStaticFieldInitializers().getWithKey(keyField);
                        if (initializer.type == Exprent.EXPRENT_FUNCTION) {
                            FunctionExprent fexpr = (FunctionExprent) initializer;

                            if (fexpr.getFuncType() == FunctionExprent.FUNCTION_BOOL_NOT &&
                                    fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_INVOCATION) {

                                InvocationExprent invexpr = (InvocationExprent) fexpr.getLstOperands().get(0);

                                if (invexpr.getInstance() != null &&
                                        invexpr.getInstance().type == Exprent.EXPRENT_CONST &&
                                        "desiredAssertionStatus".equals(invexpr.getName()) &&
                                        "java/lang/Class".equals(invexpr.getClassname()) &&
                                        invexpr.getLstParameters().isEmpty()) {

                                    ConstExprent cexpr = (ConstExprent) invexpr.getInstance();
                                    if (VarType.VARTYPE_CLASS.equals(cexpr.getConstType())) {

                                        ClassNode nd = node;
                                        while (nd != null) {
                                            if (nd.getWrapper().getClassStruct().qualifiedName.equals(cexpr.getValue())) {
                                                break;
                                            }
                                            nd = nd.parent;
                                        }

                                        if (nd != null) { // found enclosing class with the same name
                                            return fd;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }


        return null;
    }
 
Example 12
Source File: LambdaProcessor.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
public void processClass(ClassNode node) throws IOException {
    for (ClassNode child : node.nested) {
        processClass(child);
    }

    ClassesProcessor clProcessor = DecompilerContext.getClassProcessor();
    StructClass cl = node.classStruct;

    if (cl.getBytecodeVersion() < CodeConstants.BYTECODE_JAVA_8) { // lambda beginning with Java 8
        return;
    }

    StructBootstrapMethodsAttribute bootstrap =
            (StructBootstrapMethodsAttribute) cl.getAttribute(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS);
    if (bootstrap == null || bootstrap.getMethodsNumber() == 0) {
        return; // no bootstrap constants in pool
    }

    BitSet lambda_methods = new BitSet();

    // find lambda bootstrap constants
    for (int i = 0; i < bootstrap.getMethodsNumber(); ++i) {
        LinkConstant method_ref = bootstrap.getMethodReference(i); // method handle

        // FIXME: extend for Eclipse etc. at some point
        if (JAVAC_LAMBDA_CLASS.equals(method_ref.classname) &&
                (JAVAC_LAMBDA_METHOD.equals(method_ref.elementname) || JAVAC_LAMBDA_ALT_METHOD.equals(method_ref.elementname))) {
            lambda_methods.set(i);
        }
    }

    if (lambda_methods.isEmpty()) {
        return; // no lambda bootstrap constant found
    }

    Map<String, String> mapMethodsLambda = new HashMap<>();

    // iterate over code and find invocations of bootstrap methods. Replace them with anonymous classes.
    for (StructMethod mt : cl.getMethods()) {
        mt.expandData();

        InstructionSequence seq = mt.getInstructionSequence();
        if (seq != null && seq.length() > 0) {
            int len = seq.length();

            for (int i = 0; i < len; ++i) {
                Instruction instr = seq.getInstr(i);

                if (instr.opcode == CodeConstants.opc_invokedynamic) {
                    LinkConstant invoke_dynamic = cl.getPool().getLinkConstant(instr.operand(0));

                    if (lambda_methods.get(invoke_dynamic.index1)) { // lambda invocation found

                        List<PooledConstant> bootstrap_arguments = bootstrap.getMethodArguments(invoke_dynamic.index1);
                        MethodDescriptor md = MethodDescriptor.parseDescriptor(invoke_dynamic.descriptor);

                        String lambda_class_name = md.ret.value;
                        String lambda_method_name = invoke_dynamic.elementname;
                        String lambda_method_descriptor = ((PrimitiveConstant) bootstrap_arguments.get(2)).getString(); // method type

                        LinkConstant content_method_handle = (LinkConstant) bootstrap_arguments.get(1);

                        ClassNode node_lambda = new ClassNode(content_method_handle.classname, content_method_handle.elementname,
                                content_method_handle.descriptor, content_method_handle.index1,
                                lambda_class_name, lambda_method_name, lambda_method_descriptor, cl);
                        node_lambda.simpleName = cl.qualifiedName + "##Lambda_" + invoke_dynamic.index1 + "_" + invoke_dynamic.index2;
                        node_lambda.enclosingMethod = InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor());

                        node.nested.add(node_lambda);
                        node_lambda.parent = node;

                        clProcessor.getMapRootClasses().put(node_lambda.simpleName, node_lambda);
                        if (!node_lambda.lambdaInformation.is_method_reference) {
                            mapMethodsLambda.put(node_lambda.lambdaInformation.content_method_key, node_lambda.simpleName);
                        }
                    }
                }
            }
        }

        mt.releaseResources();
    }

    // build class hierarchy on lambda
    for (ClassNode nd : node.nested) {
        if (nd.type == ClassNode.CLASS_LAMBDA) {
            String parent_class_name = mapMethodsLambda.get(nd.enclosingMethod);
            if (parent_class_name != null) {
                ClassNode parent_class = clProcessor.getMapRootClasses().get(parent_class_name);

                parent_class.nested.add(nd);
                nd.parent = parent_class;
            }
        }
    }

    // FIXME: mixed hierarchy?
}
 
Example 13
Source File: AssertProcessor.java    From JByteMod-Beta with GNU General Public License v2.0 4 votes vote down vote up
private static StructField findAssertionField(ClassNode node) {

    ClassWrapper wrapper = node.getWrapper();

    boolean noSynthFlag = DecompilerContext.getOption(IFernflowerPreferences.SYNTHETIC_NOT_SET);

    for (StructField fd : wrapper.getClassStruct().getFields()) {

      String keyField = InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor());

      // initializer exists
      if (wrapper.getStaticFieldInitializers().containsKey(keyField)) {

        // access flags set
        if (fd.hasModifier(CodeConstants.ACC_STATIC) && fd.hasModifier(CodeConstants.ACC_FINAL) && (noSynthFlag || fd.isSynthetic())) {

          // field type boolean
          FieldDescriptor fdescr = FieldDescriptor.parseDescriptor(fd.getDescriptor());
          if (VarType.VARTYPE_BOOLEAN.equals(fdescr.type)) {

            Exprent initializer = wrapper.getStaticFieldInitializers().getWithKey(keyField);
            if (initializer.type == Exprent.EXPRENT_FUNCTION) {
              FunctionExprent fexpr = (FunctionExprent) initializer;

              if (fexpr.getFuncType() == FunctionExprent.FUNCTION_BOOL_NOT && fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_INVOCATION) {

                InvocationExprent invexpr = (InvocationExprent) fexpr.getLstOperands().get(0);

                if (invexpr.getInstance() != null && invexpr.getInstance().type == Exprent.EXPRENT_CONST
                    && "desiredAssertionStatus".equals(invexpr.getName()) && "java/lang/Class".equals(invexpr.getClassname())
                    && invexpr.getLstParameters().isEmpty()) {

                  ConstExprent cexpr = (ConstExprent) invexpr.getInstance();
                  if (VarType.VARTYPE_CLASS.equals(cexpr.getConstType())) {

                    ClassNode nd = node;
                    while (nd != null) {
                      if (nd.getWrapper().getClassStruct().qualifiedName.equals(cexpr.getValue())) {
                        break;
                      }
                      nd = nd.parent;
                    }

                    if (nd != null) { // found enclosing class with the same name
                      return fd;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }

    return null;
  }
 
Example 14
Source File: LambdaProcessor.java    From JByteMod-Beta with GNU General Public License v2.0 4 votes vote down vote up
public boolean hasLambda(ClassNode node) throws IOException {
  ClassesProcessor clProcessor = DecompilerContext.getClassProcessor();
  StructClass cl = node.classStruct;

  if (cl.getBytecodeVersion() < CodeConstants.BYTECODE_JAVA_8) { // lambda beginning with Java 8
    return false;
  }

  StructBootstrapMethodsAttribute bootstrap = (StructBootstrapMethodsAttribute) cl.getAttributes()
      .getWithKey(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS);
  if (bootstrap == null || bootstrap.getMethodsNumber() == 0) {
    return false; // no bootstrap constants in pool
  }

  BitSet lambda_methods = new BitSet();

  // find lambda bootstrap constants
  for (int i = 0; i < bootstrap.getMethodsNumber(); ++i) {
    LinkConstant method_ref = bootstrap.getMethodReference(i); // method handle

    // FIXME: extend for Eclipse etc. at some point
    if (JAVAC_LAMBDA_CLASS.equals(method_ref.classname)
        && (JAVAC_LAMBDA_METHOD.equals(method_ref.elementname) || JAVAC_LAMBDA_ALT_METHOD.equals(method_ref.elementname))) {
      lambda_methods.set(i);
    }
  }

  if (lambda_methods.isEmpty()) {
    return false; // no lambda bootstrap constant found
  }

  Map<String, String> mapMethodsLambda = new HashMap<>();

  // iterate over code and find invocations of bootstrap methods. Replace them with anonymous classes.
  for (StructMethod mt : cl.getMethods()) {
    mt.expandData();

    InstructionSequence seq = mt.getInstructionSequence();
    if (seq != null && seq.length() > 0) {
      int len = seq.length();

      for (int i = 0; i < len; ++i) {
        Instruction instr = seq.getInstr(i);

        if (instr.opcode == CodeConstants.opc_invokedynamic) {
          LinkConstant invoke_dynamic = cl.getPool().getLinkConstant(instr.getOperand(0));

          if (lambda_methods.get(invoke_dynamic.index1)) { // lambda invocation found

            List<PooledConstant> bootstrap_arguments = bootstrap.getMethodArguments(invoke_dynamic.index1);
            MethodDescriptor md = MethodDescriptor.parseDescriptor(invoke_dynamic.descriptor);

            String lambda_class_name = md.ret.value;
            String lambda_method_name = invoke_dynamic.elementname;
            String lambda_method_descriptor = ((PrimitiveConstant) bootstrap_arguments.get(2)).getString(); // method type

            LinkConstant content_method_handle = (LinkConstant) bootstrap_arguments.get(1);

            ClassNode node_lambda = new ClassNode(content_method_handle.classname, content_method_handle.elementname,
                content_method_handle.descriptor, content_method_handle.index1, lambda_class_name, lambda_method_name, lambda_method_descriptor,
                cl);
            node_lambda.simpleName = cl.qualifiedName + "##Lambda_" + invoke_dynamic.index1 + "_" + invoke_dynamic.index2;
            node_lambda.enclosingMethod = InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor());

            node.nested.add(node_lambda);
            node_lambda.parent = node;

            clProcessor.getMapRootClasses().put(node_lambda.simpleName, node_lambda);
            if (!node_lambda.lambdaInformation.is_method_reference) {
              mapMethodsLambda.put(node_lambda.lambdaInformation.content_method_key, node_lambda.simpleName);
            }
          }
        }
      }
    }

    mt.releaseResources();
  }

  // build class hierarchy on lambda
  for (ClassNode nd : node.nested) {
    if (nd.type == ClassNode.CLASS_LAMBDA) {
      String parent_class_name = mapMethodsLambda.get(nd.enclosingMethod);
      if (parent_class_name != null) {
        ClassNode parent_class = clProcessor.getMapRootClasses().get(parent_class_name);

        parent_class.nested.add(nd);
        nd.parent = parent_class;
      }
    }
  }

  // FIXME: mixed hierarchy?

  return false;
}