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, ...] -> ..., 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 }