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