Sat, 07 Nov 2020 10:30:02 +0800
Added tag mips-jdk8u275-b01 for changeset fdbe50121f48
1 /*
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.xml.internal.bind.v2.bytecode;
28 import java.io.ByteArrayOutputStream;
29 import java.io.DataInputStream;
30 import java.io.DataOutputStream;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.util.logging.Level;
34 import java.util.logging.Logger;
36 import com.sun.xml.internal.bind.Util;
38 /**
39 * Replaces a few constant pool tokens from a class "template" and then loads it into the VM.
40 *
41 * @author Kohsuke Kawaguchi
42 */
43 public final class ClassTailor {
45 private ClassTailor() {} // no instanciation please
47 private static final Logger logger = Util.getClassLogger();
49 /**
50 * Returns the class name in the JVM format (such as "java/lang/String")
51 */
52 public static String toVMClassName( Class c ) {
53 assert !c.isPrimitive();
54 if(c.isArray())
55 // I have no idea why it is designed like this, but javap says so.
56 return toVMTypeName(c);
57 return c.getName().replace('.','/');
58 }
60 public static String toVMTypeName( Class c ) {
61 if(c.isArray()) {
62 // TODO: study how an array type is encoded.
63 return '['+toVMTypeName(c.getComponentType());
64 }
65 if(c.isPrimitive()) {
66 if(c==Boolean.TYPE) return "Z";
67 if(c==Character.TYPE) return "C";
68 if(c==Byte.TYPE) return "B";
69 if(c==Double.TYPE) return "D";
70 if(c==Float.TYPE) return "F";
71 if(c==Integer.TYPE) return "I";
72 if(c==Long.TYPE) return "J";
73 if(c==Short.TYPE) return "S";
75 throw new IllegalArgumentException(c.getName());
76 }
77 return 'L'+c.getName().replace('.','/')+';';
78 }
82 public static byte[] tailor( Class templateClass, String newClassName, String... replacements ) {
83 String vmname = toVMClassName(templateClass);
84 return tailor(
85 SecureLoader.getClassClassLoader(templateClass).getResourceAsStream(vmname+".class"),
86 vmname, newClassName, replacements );
87 }
90 /**
91 * Customizes a class file by replacing constant pools.
92 *
93 * @param image
94 * The image of the template class.
95 * @param replacements
96 * A list of pair of strings that specify the substitution
97 * {@code String[]{search_0, replace_0, search_1, replace_1, ..., search_n, replace_n }}
98 *
99 * The search strings found in the constant pool will be replaced by the corresponding
100 * replacement string.
101 */
102 public static byte[] tailor( InputStream image, String templateClassName, String newClassName, String... replacements ) {
103 DataInputStream in = new DataInputStream(image);
105 try {
106 ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
107 DataOutputStream out = new DataOutputStream(baos);
109 // skip until the constant pool count
110 long l = in.readLong();
111 out.writeLong(l);
113 // read the constant pool size
114 short count = in.readShort();
115 out.writeShort(count);
117 // replace constant pools
118 for( int i=0; i<count; i++ ) {
119 byte tag = in.readByte();
120 out.writeByte(tag);
121 switch(tag) {
122 case 0:
123 // this isn't described in the spec,
124 // but class files often seem to have this '0' tag.
125 // we can apparently just ignore it, but not sure
126 // what this really means.
127 break;
129 case 1: // CONSTANT_UTF8
130 {
131 String value = in.readUTF();
132 if(value.equals(templateClassName))
133 value = newClassName;
134 else {
135 for( int j=0; j<replacements.length; j+=2 )
136 if(value.equals(replacements[j])) {
137 value = replacements[j+1];
138 break;
139 }
140 }
141 out.writeUTF(value);
142 }
143 break;
145 case 3: // CONSTANT_Integer
146 case 4: // CONSTANT_Float
147 out.writeInt(in.readInt());
148 break;
150 case 5: // CONSTANT_Long
151 case 6: // CONSTANT_Double
152 i++; // doubles and longs take two entries
153 out.writeLong(in.readLong());
154 break;
156 case 7: // CONSTANT_Class
157 case 8: // CONSTANT_String
158 out.writeShort(in.readShort());
159 break;
161 case 9: // CONSTANT_Fieldref
162 case 10: // CONSTANT_Methodref
163 case 11: // CONSTANT_InterfaceMethodref
164 case 12: // CONSTANT_NameAndType
165 out.writeInt(in.readInt());
166 break;
168 default:
169 throw new IllegalArgumentException("Unknown constant type "+tag);
170 }
171 }
173 // then copy the rest
174 byte[] buf = new byte[512];
175 int len;
176 while((len=in.read(buf))>0)
177 out.write(buf,0,len);
179 in.close();
180 out.close();
182 // by now we got the properly tailored class file image
183 return baos.toByteArray();
185 } catch( IOException e ) {
186 // never happen
187 logger.log(Level.WARNING,"failed to tailor",e);
188 return null;
189 }
190 }
191 }