View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.bcel.generic;
20  
21  import java.io.DataOutputStream;
22  import java.io.IOException;
23  
24  import org.apache.bcel.ExceptionConst;
25  import org.apache.bcel.classfile.ConstantPool;
26  import org.apache.bcel.util.ByteSequence;
27  
28  /**
29   * MULTIANEWARRAY - Create new mutidimensional array of references
30   *
31   * <pre>
32   * Stack: ..., count1, [count2, ...] -&gt; ..., arrayref
33   * </pre>
34   */
35  public class MULTIANEWARRAY extends CPInstruction implements LoadClass, AllocationInstruction, ExceptionThrower {
36  
37      private short dimensions;
38  
39      /**
40       * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
41       */
42      MULTIANEWARRAY() {
43      }
44  
45      /**
46       * Constructs a MULTIANEWARRAY instruction.
47       *
48       * @param index index into constant pool.
49       * @param dimensions number of dimensions.
50       */
51      public MULTIANEWARRAY(final int index, final short dimensions) {
52          super(org.apache.bcel.Const.MULTIANEWARRAY, index);
53          if (dimensions < 1 || dimensions > org.apache.bcel.Const.MAX_BYTE) {
54              throw new ClassGenException("Invalid dimensions value: " + dimensions);
55          }
56          this.dimensions = dimensions;
57          super.setLength(4);
58      }
59  
60      /**
61       * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call
62       * methods according to the class hierarchy in descending order, that is, the most specific visitXXX() call comes last.
63       *
64       * @param v Visitor object.
65       */
66      @Override
67      public void accept(final Visitor v) {
68          v.visitLoadClass(this);
69          v.visitAllocationInstruction(this);
70          v.visitExceptionThrower(this);
71          v.visitTypedInstruction(this);
72          v.visitCPInstruction(this);
73          v.visitMULTIANEWARRAY(this);
74      }
75  
76      /**
77       * Also works for instructions whose stack effect depends on the constant pool entry they reference.
78       *
79       * @return Number of words consumed from stack by this instruction.
80       */
81      @Override
82      public int consumeStack(final ConstantPoolGen cpg) {
83          return dimensions;
84      }
85  
86      /**
87       * Dumps instruction as byte code to stream out.
88       *
89       * @param out Output stream.
90       */
91      @Override
92      public void dump(final DataOutputStream out) throws IOException {
93          out.writeByte(super.getOpcode());
94          out.writeShort(super.getIndex());
95          out.writeByte(dimensions);
96      }
97  
98      /**
99       * Gets the number of dimensions.
100      *
101      * @return number of dimensions to be created.
102      */
103     public final short getDimensions() {
104         return dimensions;
105     }
106 
107     @Override
108     public Class<?>[] getExceptions() {
109         return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_CLASS_AND_INTERFACE_RESOLUTION, ExceptionConst.ILLEGAL_ACCESS_ERROR,
110             ExceptionConst.NEGATIVE_ARRAY_SIZE_EXCEPTION);
111     }
112 
113     @Override
114     public ObjectType getLoadClassType(final ConstantPoolGen cpg) {
115         Type t = getType(cpg);
116         if (t instanceof ArrayType) {
117             t = ((ArrayType) t).getBasicType();
118         }
119         return t instanceof ObjectType ? (ObjectType) t : null;
120     }
121 
122     /**
123      * Reads needed data (that is, no. dimension) from file.
124      */
125     @Override
126     protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {
127         super.initFromFile(bytes, wide);
128         dimensions = (short) bytes.readUnsignedByte();
129         super.setLength(4);
130     }
131 
132     /**
133      * @return mnemonic for instruction.
134      */
135     @Override
136     public String toString(final boolean verbose) {
137         return super.toString(verbose) + " " + super.getIndex() + " " + dimensions;
138     }
139 
140     /**
141      * @return mnemonic for instruction with symbolic references resolved.
142      */
143     @Override
144     public String toString(final ConstantPool cp) {
145         return super.toString(cp) + " " + dimensions;
146     }
147 }