001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020package org.apache.bcel.classfile; 021 022import java.io.DataInput; 023import java.io.DataOutputStream; 024import java.io.IOException; 025import java.util.Arrays; 026 027import org.apache.bcel.Const; 028import org.apache.commons.lang3.ArrayUtils; 029 030/** 031 * This class represents a bootstrap method attribute, that is, the bootstrap method ref, the number of bootstrap arguments 032 * and an array of the bootstrap arguments. 033 * 034 * @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.23"> The class File Format : 035 * The BootstrapMethods Attribute</a> 036 * @since 6.0 037 */ 038public class BootstrapMethod implements Cloneable { 039 040 static final BootstrapMethod[] EMPTY_ARRAY = {}; 041 042 /** Index of the CONSTANT_MethodHandle_info structure in the constant_pool table */ 043 private int bootstrapMethodRef; 044 045 /** Array of references to the constant_pool table */ 046 private int[] bootstrapArguments; 047 048 /** 049 * Initialize from another object. 050 * 051 * @param c Source to copy. 052 */ 053 public BootstrapMethod(final BootstrapMethod c) { 054 this(c.getBootstrapMethodRef(), c.getBootstrapArguments()); 055 } 056 057 /** 058 * Constructs object from input stream. 059 * 060 * @param input Input stream. 061 * @throws IOException if an I/O error occurs. 062 */ 063 BootstrapMethod(final DataInput input) throws IOException { 064 this(input.readUnsignedShort(), input.readUnsignedShort()); 065 066 for (int i = 0; i < bootstrapArguments.length; i++) { 067 bootstrapArguments[i] = input.readUnsignedShort(); 068 } 069 } 070 071 // helper method 072 private BootstrapMethod(final int bootstrapMethodRef, final int numBootstrapArguments) { 073 this(bootstrapMethodRef, new int[numBootstrapArguments]); 074 } 075 076 /** 077 * Constructs a BootstrapMethod. 078 * 079 * @param bootstrapMethodRef int index into constant_pool of CONSTANT_MethodHandle. 080 * @param bootstrapArguments int[] indices into constant_pool of CONSTANT_[type]_info. 081 */ 082 public BootstrapMethod(final int bootstrapMethodRef, final int[] bootstrapArguments) { 083 this.bootstrapMethodRef = bootstrapMethodRef; 084 setBootstrapArguments(bootstrapArguments); 085 } 086 087 /** 088 * Creates a deep copy of this object. 089 * 090 * @return deep copy of this object. 091 */ 092 public BootstrapMethod copy() { 093 try { 094 return (BootstrapMethod) clone(); 095 } catch (final CloneNotSupportedException ignore) { 096 // TODO should this throw? 097 } 098 return null; 099 } 100 101 /** 102 * Dumps object to file stream in binary format. 103 * 104 * @param file Output file stream. 105 * @throws IOException if an I/O error occurs. 106 */ 107 public final void dump(final DataOutputStream file) throws IOException { 108 file.writeShort(bootstrapMethodRef); 109 file.writeShort(bootstrapArguments.length); 110 for (final int bootstrapArgument : bootstrapArguments) { 111 file.writeShort(bootstrapArgument); 112 } 113 } 114 115 /** 116 * Gets the bootstrap arguments. 117 * 118 * @return int[] of bootstrap_method indices into constant_pool of CONSTANT_[type]_info. 119 */ 120 public int[] getBootstrapArguments() { 121 return bootstrapArguments; 122 } 123 124 /** 125 * Gets the bootstrap method reference. 126 * 127 * @return index into constant_pool of bootstrap_method. 128 */ 129 public int getBootstrapMethodRef() { 130 return bootstrapMethodRef; 131 } 132 133 /** 134 * Gets the count of number of bootstrap arguments. 135 * 136 * @return count of number of bootstrap arguments. 137 */ 138 public int getNumBootstrapArguments() { 139 return bootstrapArguments.length; 140 } 141 142 /** 143 * Sets the bootstrap arguments. 144 * 145 * @param bootstrapArguments int[] indices into constant_pool of CONSTANT_[type]_info. 146 */ 147 public void setBootstrapArguments(final int[] bootstrapArguments) { 148 this.bootstrapArguments = ArrayUtils.nullToEmpty(bootstrapArguments); 149 } 150 151 /** 152 * Sets the bootstrap method reference. 153 * 154 * @param bootstrapMethodRef int index into constant_pool of CONSTANT_MethodHandle. 155 */ 156 public void setBootstrapMethodRef(final int bootstrapMethodRef) { 157 this.bootstrapMethodRef = bootstrapMethodRef; 158 } 159 160 /** 161 * Gets a string representation. 162 * 163 * @return String representation. 164 */ 165 @Override 166 public final String toString() { 167 return "BootstrapMethod(" + bootstrapMethodRef + ", " + bootstrapArguments.length + ", " + Arrays.toString(bootstrapArguments) + ")"; 168 } 169 170 /** 171 * Gets a resolved string representation. 172 * 173 * @param constantPool the constant pool. 174 * @return Resolved string representation. 175 */ 176 public final String toString(final ConstantPool constantPool) { 177 final StringBuilder buf = new StringBuilder(); 178 final String bootstrapMethodName = constantPool.constantToString(bootstrapMethodRef, Const.CONSTANT_MethodHandle); 179 buf.append(Utility.compactClassName(bootstrapMethodName, false)); 180 final int bootstrapArgumentsLen = bootstrapArguments.length; 181 if (bootstrapArgumentsLen > 0) { 182 buf.append("\nMethod Arguments:"); 183 for (int i = 0; i < bootstrapArgumentsLen; i++) { 184 buf.append("\n ").append(i).append(": "); 185 buf.append(constantPool.constantToString(constantPool.getConstant(bootstrapArguments[i]))); 186 } 187 } 188 return buf.toString(); 189 } 190}