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 018package org.apache.bcel.classfile; 019 020import java.io.DataInput; 021import java.io.DataOutputStream; 022import java.io.IOException; 023import java.util.Arrays; 024 025import org.apache.bcel.Const; 026 027/** 028 * This class represents a bootstrap method attribute, i.e., the bootstrap method ref, the number of bootstrap arguments 029 * and an array of the bootstrap arguments. 030 * 031 * @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.23"> The class File Format : 032 * The BootstrapMethods Attribute</a> 033 * @since 6.0 034 */ 035public class BootstrapMethod implements Cloneable { 036 037 /** Index of the CONSTANT_MethodHandle_info structure in the constant_pool table */ 038 private int bootstrapMethodRef; 039 040 /** Array of references to the constant_pool table */ 041 private int[] bootstrapArguments; 042 043 /** 044 * Initialize from another object. 045 */ 046 public BootstrapMethod(final BootstrapMethod c) { 047 this(c.getBootstrapMethodRef(), c.getBootstrapArguments()); 048 } 049 050 /** 051 * Construct object from input stream. 052 * 053 * @param input Input stream 054 * @throws IOException if an I/O error occurs. 055 */ 056 BootstrapMethod(final DataInput input) throws IOException { 057 this(input.readUnsignedShort(), input.readUnsignedShort()); 058 059 for (int i = 0; i < bootstrapArguments.length; i++) { 060 bootstrapArguments[i] = input.readUnsignedShort(); 061 } 062 } 063 064 // helper method 065 private BootstrapMethod(final int bootstrapMethodRef, final int numBootstrapArguments) { 066 this(bootstrapMethodRef, new int[numBootstrapArguments]); 067 } 068 069 /** 070 * @param bootstrapMethodRef int index into constant_pool of CONSTANT_MethodHandle 071 * @param bootstrapArguments int[] indices into constant_pool of CONSTANT_[type]_info 072 */ 073 public BootstrapMethod(final int bootstrapMethodRef, final int[] bootstrapArguments) { 074 this.bootstrapMethodRef = bootstrapMethodRef; 075 this.bootstrapArguments = bootstrapArguments; 076 } 077 078 /** 079 * @return deep copy of this object 080 */ 081 public BootstrapMethod copy() { 082 try { 083 return (BootstrapMethod) clone(); 084 } catch (final CloneNotSupportedException e) { 085 // TODO should this throw? 086 } 087 return null; 088 } 089 090 /** 091 * Dump object to file stream in binary format. 092 * 093 * @param file Output file stream 094 * @throws IOException if an I/O error occurs. 095 */ 096 public final void dump(final DataOutputStream file) throws IOException { 097 file.writeShort(bootstrapMethodRef); 098 file.writeShort(bootstrapArguments.length); 099 for (final int bootstrapArgument : bootstrapArguments) { 100 file.writeShort(bootstrapArgument); 101 } 102 } 103 104 /** 105 * @return int[] of bootstrap_method indices into constant_pool of CONSTANT_[type]_info 106 */ 107 public int[] getBootstrapArguments() { 108 return bootstrapArguments; 109 } 110 111 /** 112 * @return index into constant_pool of bootstrap_method 113 */ 114 public int getBootstrapMethodRef() { 115 return bootstrapMethodRef; 116 } 117 118 /** 119 * @return count of number of boostrap arguments 120 */ 121 public int getNumBootstrapArguments() { 122 return bootstrapArguments.length; 123 } 124 125 /** 126 * @param bootstrapArguments int[] indices into constant_pool of CONSTANT_[type]_info 127 */ 128 public void setBootstrapArguments(final int[] bootstrapArguments) { 129 this.bootstrapArguments = bootstrapArguments; 130 } 131 132 /** 133 * @param bootstrapMethodRef int index into constant_pool of CONSTANT_MethodHandle 134 */ 135 public void setBootstrapMethodRef(final int bootstrapMethodRef) { 136 this.bootstrapMethodRef = bootstrapMethodRef; 137 } 138 139 /** 140 * @return String representation. 141 */ 142 @Override 143 public final String toString() { 144 return "BootstrapMethod(" + bootstrapMethodRef + ", " + bootstrapArguments.length + ", " + Arrays.toString(bootstrapArguments) + ")"; 145 } 146 147 /** 148 * @return Resolved string representation 149 */ 150 public final String toString(final ConstantPool constantPool) { 151 final StringBuilder buf = new StringBuilder(); 152 final String bootstrapMethodName = constantPool.constantToString(bootstrapMethodRef, Const.CONSTANT_MethodHandle); 153 buf.append(Utility.compactClassName(bootstrapMethodName, false)); 154 final int bootstrapArgumentsLen = bootstrapArguments.length; 155 if (bootstrapArgumentsLen > 0) { 156 buf.append("\nMethod Arguments:"); 157 for (int i = 0; i < bootstrapArgumentsLen; i++) { 158 buf.append("\n ").append(i).append(": "); 159 buf.append(constantPool.constantToString(constantPool.getConstant(bootstrapArguments[i]))); 160 } 161 } 162 return buf.toString(); 163 } 164}