1 /*
   2  * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.bcel.internal.generic;
  22 
  23 import java.io.DataOutputStream;
  24 import java.io.IOException;
  25 
  26 import com.sun.org.apache.bcel.internal.Const;
  27 import com.sun.org.apache.bcel.internal.ExceptionConst;
  28 import com.sun.org.apache.bcel.internal.classfile.ConstantInvokeDynamic;
  29 import com.sun.org.apache.bcel.internal.classfile.ConstantNameAndType;
  30 import com.sun.org.apache.bcel.internal.classfile.ConstantPool;
  31 import com.sun.org.apache.bcel.internal.util.ByteSequence;
  32 
  33 /**
  34  * Class for INVOKEDYNAMIC. Not an instance of InvokeInstruction, since that class
  35  * expects to be able to get the class of the method. Ignores the bootstrap
  36  * mechanism entirely.
  37  *
  38  * @see
  39  * <a href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.invokedynamic">
  40  * The invokedynamic instruction in The Java Virtual Machine Specification</a>
  41  * @since 6.0
  42  * @LastModified: Jan 2020
  43  */
  44 public class INVOKEDYNAMIC extends InvokeInstruction {
  45 
  46     /**
  47      * Empty constructor needed for Instruction.readInstruction.
  48      * Not to be used otherwise.
  49      */
  50     INVOKEDYNAMIC() {
  51     }
  52 
  53 
  54     public INVOKEDYNAMIC(final int index) {
  55         super(Const.INVOKEDYNAMIC, index);
  56     }
  57 
  58 
  59     /**
  60      * Dump instruction as byte code to stream out.
  61      * @param out Output stream
  62      */
  63     @Override
  64     public void dump( final DataOutputStream out ) throws IOException {
  65         out.writeByte(super.getOpcode());
  66         out.writeShort(super.getIndex());
  67         out.writeByte(0);
  68         out.writeByte(0);
  69        }
  70 
  71 
  72     /**
  73      * Read needed data (i.e., index) from file.
  74      */
  75     @Override
  76     protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException {
  77         super.initFromFile(bytes, wide);
  78         super.setLength(5);
  79         bytes.readByte(); // Skip 0 byte
  80         bytes.readByte(); // Skip 0 byte
  81     }
  82 
  83 
  84     /**
  85      * @return mnemonic for instruction with symbolic references resolved
  86      */
  87     @Override
  88     public String toString( final ConstantPool cp ) {
  89         return super.toString(cp);
  90     }
  91 
  92 
  93     @Override
  94     public Class<?>[] getExceptions() {
  95         return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_INTERFACE_METHOD_RESOLUTION,
  96             ExceptionConst.UNSATISFIED_LINK_ERROR,
  97             ExceptionConst.ABSTRACT_METHOD_ERROR,
  98             ExceptionConst.ILLEGAL_ACCESS_ERROR,
  99             ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR);
 100     }
 101 
 102 
 103     /**
 104      * Call corresponding visitor method(s). The order is:
 105      * Call visitor methods of implemented interfaces first, then
 106      * call methods according to the class hierarchy in descending order,
 107      * i.e., the most specific visitXXX() call comes last.
 108      *
 109      * @param v Visitor object
 110      */
 111     @Override
 112     public void accept( final Visitor v ) {
 113         v.visitExceptionThrower(this);
 114         v.visitTypedInstruction(this);
 115         v.visitStackConsumer(this);
 116         v.visitStackProducer(this);
 117         v.visitLoadClass(this);
 118         v.visitCPInstruction(this);
 119         v.visitFieldOrMethod(this);
 120         v.visitInvokeInstruction(this);
 121         v.visitINVOKEDYNAMIC(this);
 122     }
 123 
 124     /**
 125      * Override the parent method because our classname is held elsewhere.
 126      *
 127      * @param cpg the ConstantPool generator
 128      * @deprecated in FieldOrMethod
 129      *
 130      * @return name of the referenced class/interface
 131      */
 132     @Override
 133     @Deprecated
 134     public String getClassName( final ConstantPoolGen cpg ) {
 135         final ConstantPool cp = cpg.getConstantPool();
 136         final ConstantInvokeDynamic cid = (ConstantInvokeDynamic) cp.getConstant(super.getIndex(), Const.CONSTANT_InvokeDynamic);
 137         return ((ConstantNameAndType) cp.getConstant(cid.getNameAndTypeIndex())).getName(cp);
 138     }
 139 
 140 
 141     /**
 142      * Since InvokeDynamic doesn't refer to a reference type, just return java.lang.Object,
 143      * as that is the only type we can say for sure the reference will be.
 144      *
 145      * @param cpg
 146      *            the ConstantPoolGen used to create the instruction
 147      * @return an ObjectType for java.lang.Object
 148      * @since 6.1
 149      */
 150     @Override
 151     public ReferenceType getReferenceType(final ConstantPoolGen cpg) {
 152         return new ObjectType(Object.class.getName());
 153     }
 154 }