001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 */
018 package org.apache.bcel.generic;
019
020 import java.io.DataOutputStream;
021 import java.io.IOException;
022 import org.apache.bcel.ExceptionConstants;
023 import org.apache.bcel.classfile.ConstantPool;
024 import org.apache.bcel.util.ByteSequence;
025
026 /**
027 * MULTIANEWARRAY - Create new mutidimensional array of references
028 * <PRE>Stack: ..., count1, [count2, ...] -> ..., arrayref</PRE>
029 *
030 * @version $Id: MULTIANEWARRAY.java 1152072 2011-07-29 01:54:05Z dbrosius $
031 * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
032 */
033 public class MULTIANEWARRAY extends CPInstruction implements LoadClass, AllocationInstruction,
034 ExceptionThrower {
035
036 private static final long serialVersionUID = -7439639244808941662L;
037 private short dimensions;
038
039
040 /**
041 * Empty constructor needed for the Class.newInstance() statement in
042 * Instruction.readInstruction(). Not to be used otherwise.
043 */
044 MULTIANEWARRAY() {
045 }
046
047
048 public MULTIANEWARRAY(int index, short dimensions) {
049 super(org.apache.bcel.Constants.MULTIANEWARRAY, index);
050 if (dimensions < 1) {
051 throw new ClassGenException("Invalid dimensions value: " + dimensions);
052 }
053 this.dimensions = dimensions;
054 length = 4;
055 }
056
057
058 /**
059 * Dump instruction as byte code to stream out.
060 * @param out Output stream
061 */
062 @Override
063 public void dump( DataOutputStream out ) throws IOException {
064 out.writeByte(opcode);
065 out.writeShort(index);
066 out.writeByte(dimensions);
067 }
068
069
070 /**
071 * Read needed data (i.e., no. dimension) from file.
072 */
073 @Override
074 protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
075 super.initFromFile(bytes, wide);
076 dimensions = bytes.readByte();
077 length = 4;
078 }
079
080
081 /**
082 * @return number of dimensions to be created
083 */
084 public final short getDimensions() {
085 return dimensions;
086 }
087
088
089 /**
090 * @return mnemonic for instruction
091 */
092 @Override
093 public String toString( boolean verbose ) {
094 return super.toString(verbose) + " " + index + " " + dimensions;
095 }
096
097
098 /**
099 * @return mnemonic for instruction with symbolic references resolved
100 */
101 @Override
102 public String toString( ConstantPool cp ) {
103 return super.toString(cp) + " " + dimensions;
104 }
105
106
107 /**
108 * Also works for instructions whose stack effect depends on the
109 * constant pool entry they reference.
110 * @return Number of words consumed from stack by this instruction
111 */
112 @Override
113 public int consumeStack( ConstantPoolGen cpg ) {
114 return dimensions;
115 }
116
117
118 public Class<?>[] getExceptions() {
119 Class<?>[] cs = new Class[2 + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length];
120 System.arraycopy(ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION, 0, cs, 0,
121 ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length);
122 cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length + 1] = ExceptionConstants.NEGATIVE_ARRAY_SIZE_EXCEPTION;
123 cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length] = ExceptionConstants.ILLEGAL_ACCESS_ERROR;
124 return cs;
125 }
126
127
128 public ObjectType getLoadClassType( ConstantPoolGen cpg ) {
129 Type t = getType(cpg);
130 if (t instanceof ArrayType) {
131 t = ((ArrayType) t).getBasicType();
132 }
133 return (t instanceof ObjectType) ? (ObjectType) t : null;
134 }
135
136
137 /**
138 * Call corresponding visitor method(s). The order is:
139 * Call visitor methods of implemented interfaces first, then
140 * call methods according to the class hierarchy in descending order,
141 * i.e., the most specific visitXXX() call comes last.
142 *
143 * @param v Visitor object
144 */
145 @Override
146 public void accept( Visitor v ) {
147 v.visitLoadClass(this);
148 v.visitAllocationInstruction(this);
149 v.visitExceptionThrower(this);
150 v.visitTypedInstruction(this);
151 v.visitCPInstruction(this);
152 v.visitMULTIANEWARRAY(this);
153 }
154 }