author | mkos |
Sun, 30 Dec 2012 00:00:00 +0100 | |
changeset 22678 | ac1ea46be942 |
parent 12009 | 4abb694f273a |
permissions | -rw-r--r-- |
12009 | 1 |
/* |
22678
ac1ea46be942
8029237: Update copyright year to match last edit in jaxws repository for 2012
mkos
parents:
12009
diff
changeset
|
2 |
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. |
12009 | 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 |
*/ |
|
25 |
||
26 |
/* |
|
27 |
* This file is available under and governed by the GNU General Public |
|
28 |
* License version 2 only, as published by the Free Software Foundation. |
|
29 |
* However, the following notice accompanied the original version of this |
|
30 |
* file: |
|
31 |
* |
|
32 |
* ASM: a very small and fast Java bytecode manipulation framework |
|
33 |
* Copyright (c) 2000-2007 INRIA, France Telecom |
|
34 |
* All rights reserved. |
|
35 |
* |
|
36 |
* Redistribution and use in source and binary forms, with or without |
|
37 |
* modification, are permitted provided that the following conditions |
|
38 |
* are met: |
|
39 |
* 1. Redistributions of source code must retain the above copyright |
|
40 |
* notice, this list of conditions and the following disclaimer. |
|
41 |
* 2. Redistributions in binary form must reproduce the above copyright |
|
42 |
* notice, this list of conditions and the following disclaimer in the |
|
43 |
* documentation and/or other materials provided with the distribution. |
|
44 |
* 3. Neither the name of the copyright holders nor the names of its |
|
45 |
* contributors may be used to endorse or promote products derived from |
|
46 |
* this software without specific prior written permission. |
|
47 |
* |
|
48 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
49 |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
50 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
51 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
|
52 |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
53 |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
54 |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
55 |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
56 |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
57 |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
|
58 |
* THE POSSIBILITY OF SUCH DAMAGE. |
|
59 |
*/ |
|
60 |
package com.sun.xml.internal.ws.org.objectweb.asm; |
|
61 |
||
62 |
/** |
|
63 |
* A {@link ClassVisitor} that generates classes in bytecode form. More |
|
64 |
* precisely this visitor generates a byte array conforming to the Java class |
|
65 |
* file format. It can be used alone, to generate a Java class "from scratch", |
|
66 |
* or with one or more {@link ClassReader ClassReader} and adapter class visitor |
|
67 |
* to generate a modified class from one or more existing Java classes. |
|
68 |
* |
|
69 |
* @author Eric Bruneton |
|
70 |
*/ |
|
71 |
public class ClassWriter implements ClassVisitor { |
|
72 |
||
73 |
/** |
|
74 |
* Flag to automatically compute the maximum stack size and the maximum |
|
75 |
* number of local variables of methods. If this flag is set, then the |
|
76 |
* arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the |
|
77 |
* {@link MethodVisitor} returned by the {@link #visitMethod visitMethod} |
|
78 |
* method will be ignored, and computed automatically from the signature and |
|
79 |
* the bytecode of each method. |
|
80 |
* |
|
81 |
* @see #ClassWriter(int) |
|
82 |
*/ |
|
83 |
public static final int COMPUTE_MAXS = 1; |
|
84 |
||
85 |
/** |
|
86 |
* Flag to automatically compute the stack map frames of methods from |
|
87 |
* scratch. If this flag is set, then the calls to the |
|
88 |
* {@link MethodVisitor#visitFrame} method are ignored, and the stack map |
|
89 |
* frames are recomputed from the methods bytecode. The arguments of the |
|
90 |
* {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and |
|
91 |
* recomputed from the bytecode. In other words, computeFrames implies |
|
92 |
* computeMaxs. |
|
93 |
* |
|
94 |
* @see #ClassWriter(int) |
|
95 |
*/ |
|
96 |
public static final int COMPUTE_FRAMES = 2; |
|
97 |
||
98 |
/** |
|
99 |
* The type of instructions without any argument. |
|
100 |
*/ |
|
101 |
static final int NOARG_INSN = 0; |
|
102 |
||
103 |
/** |
|
104 |
* The type of instructions with an signed byte argument. |
|
105 |
*/ |
|
106 |
static final int SBYTE_INSN = 1; |
|
107 |
||
108 |
/** |
|
109 |
* The type of instructions with an signed short argument. |
|
110 |
*/ |
|
111 |
static final int SHORT_INSN = 2; |
|
112 |
||
113 |
/** |
|
114 |
* The type of instructions with a local variable index argument. |
|
115 |
*/ |
|
116 |
static final int VAR_INSN = 3; |
|
117 |
||
118 |
/** |
|
119 |
* The type of instructions with an implicit local variable index argument. |
|
120 |
*/ |
|
121 |
static final int IMPLVAR_INSN = 4; |
|
122 |
||
123 |
/** |
|
124 |
* The type of instructions with a type descriptor argument. |
|
125 |
*/ |
|
126 |
static final int TYPE_INSN = 5; |
|
127 |
||
128 |
/** |
|
129 |
* The type of field and method invocations instructions. |
|
130 |
*/ |
|
131 |
static final int FIELDORMETH_INSN = 6; |
|
132 |
||
133 |
/** |
|
134 |
* The type of the INVOKEINTERFACE instruction. |
|
135 |
*/ |
|
136 |
static final int ITFMETH_INSN = 7; |
|
137 |
||
138 |
/** |
|
139 |
* The type of instructions with a 2 bytes bytecode offset label. |
|
140 |
*/ |
|
141 |
static final int LABEL_INSN = 8; |
|
142 |
||
143 |
/** |
|
144 |
* The type of instructions with a 4 bytes bytecode offset label. |
|
145 |
*/ |
|
146 |
static final int LABELW_INSN = 9; |
|
147 |
||
148 |
/** |
|
149 |
* The type of the LDC instruction. |
|
150 |
*/ |
|
151 |
static final int LDC_INSN = 10; |
|
152 |
||
153 |
/** |
|
154 |
* The type of the LDC_W and LDC2_W instructions. |
|
155 |
*/ |
|
156 |
static final int LDCW_INSN = 11; |
|
157 |
||
158 |
/** |
|
159 |
* The type of the IINC instruction. |
|
160 |
*/ |
|
161 |
static final int IINC_INSN = 12; |
|
162 |
||
163 |
/** |
|
164 |
* The type of the TABLESWITCH instruction. |
|
165 |
*/ |
|
166 |
static final int TABL_INSN = 13; |
|
167 |
||
168 |
/** |
|
169 |
* The type of the LOOKUPSWITCH instruction. |
|
170 |
*/ |
|
171 |
static final int LOOK_INSN = 14; |
|
172 |
||
173 |
/** |
|
174 |
* The type of the MULTIANEWARRAY instruction. |
|
175 |
*/ |
|
176 |
static final int MANA_INSN = 15; |
|
177 |
||
178 |
/** |
|
179 |
* The type of the WIDE instruction. |
|
180 |
*/ |
|
181 |
static final int WIDE_INSN = 16; |
|
182 |
||
183 |
/** |
|
184 |
* The instruction types of all JVM opcodes. |
|
185 |
*/ |
|
186 |
static final byte[] TYPE; |
|
187 |
||
188 |
/** |
|
189 |
* The type of CONSTANT_Class constant pool items. |
|
190 |
*/ |
|
191 |
static final int CLASS = 7; |
|
192 |
||
193 |
/** |
|
194 |
* The type of CONSTANT_Fieldref constant pool items. |
|
195 |
*/ |
|
196 |
static final int FIELD = 9; |
|
197 |
||
198 |
/** |
|
199 |
* The type of CONSTANT_Methodref constant pool items. |
|
200 |
*/ |
|
201 |
static final int METH = 10; |
|
202 |
||
203 |
/** |
|
204 |
* The type of CONSTANT_InterfaceMethodref constant pool items. |
|
205 |
*/ |
|
206 |
static final int IMETH = 11; |
|
207 |
||
208 |
/** |
|
209 |
* The type of CONSTANT_String constant pool items. |
|
210 |
*/ |
|
211 |
static final int STR = 8; |
|
212 |
||
213 |
/** |
|
214 |
* The type of CONSTANT_Integer constant pool items. |
|
215 |
*/ |
|
216 |
static final int INT = 3; |
|
217 |
||
218 |
/** |
|
219 |
* The type of CONSTANT_Float constant pool items. |
|
220 |
*/ |
|
221 |
static final int FLOAT = 4; |
|
222 |
||
223 |
/** |
|
224 |
* The type of CONSTANT_Long constant pool items. |
|
225 |
*/ |
|
226 |
static final int LONG = 5; |
|
227 |
||
228 |
/** |
|
229 |
* The type of CONSTANT_Double constant pool items. |
|
230 |
*/ |
|
231 |
static final int DOUBLE = 6; |
|
232 |
||
233 |
/** |
|
234 |
* The type of CONSTANT_NameAndType constant pool items. |
|
235 |
*/ |
|
236 |
static final int NAME_TYPE = 12; |
|
237 |
||
238 |
/** |
|
239 |
* The type of CONSTANT_Utf8 constant pool items. |
|
240 |
*/ |
|
241 |
static final int UTF8 = 1; |
|
242 |
||
243 |
/** |
|
244 |
* Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable}, |
|
245 |
* instead of the constant pool, in order to avoid clashes with normal |
|
246 |
* constant pool items in the ClassWriter constant pool's hash table. |
|
247 |
*/ |
|
248 |
static final int TYPE_NORMAL = 13; |
|
249 |
||
250 |
/** |
|
251 |
* Uninitialized type Item stored in the ClassWriter |
|
252 |
* {@link ClassWriter#typeTable}, instead of the constant pool, in order to |
|
253 |
* avoid clashes with normal constant pool items in the ClassWriter constant |
|
254 |
* pool's hash table. |
|
255 |
*/ |
|
256 |
static final int TYPE_UNINIT = 14; |
|
257 |
||
258 |
/** |
|
259 |
* Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable}, |
|
260 |
* instead of the constant pool, in order to avoid clashes with normal |
|
261 |
* constant pool items in the ClassWriter constant pool's hash table. |
|
262 |
*/ |
|
263 |
static final int TYPE_MERGED = 15; |
|
264 |
||
265 |
/** |
|
266 |
* The class reader from which this class writer was constructed, if any. |
|
267 |
*/ |
|
268 |
ClassReader cr; |
|
269 |
||
270 |
/** |
|
271 |
* Minor and major version numbers of the class to be generated. |
|
272 |
*/ |
|
273 |
int version; |
|
274 |
||
275 |
/** |
|
276 |
* Index of the next item to be added in the constant pool. |
|
277 |
*/ |
|
278 |
int index; |
|
279 |
||
280 |
/** |
|
281 |
* The constant pool of this class. |
|
282 |
*/ |
|
283 |
final ByteVector pool; |
|
284 |
||
285 |
/** |
|
286 |
* The constant pool's hash table data. |
|
287 |
*/ |
|
288 |
Item[] items; |
|
289 |
||
290 |
/** |
|
291 |
* The threshold of the constant pool's hash table. |
|
292 |
*/ |
|
293 |
int threshold; |
|
294 |
||
295 |
/** |
|
296 |
* A reusable key used to look for items in the {@link #items} hash table. |
|
297 |
*/ |
|
298 |
final Item key; |
|
299 |
||
300 |
/** |
|
301 |
* A reusable key used to look for items in the {@link #items} hash table. |
|
302 |
*/ |
|
303 |
final Item key2; |
|
304 |
||
305 |
/** |
|
306 |
* A reusable key used to look for items in the {@link #items} hash table. |
|
307 |
*/ |
|
308 |
final Item key3; |
|
309 |
||
310 |
/** |
|
311 |
* A type table used to temporarily store internal names that will not |
|
312 |
* necessarily be stored in the constant pool. This type table is used by |
|
313 |
* the control flow and data flow analysis algorithm used to compute stack |
|
314 |
* map frames from scratch. This array associates to each index <tt>i</tt> |
|
315 |
* the Item whose index is <tt>i</tt>. All Item objects stored in this |
|
316 |
* array are also stored in the {@link #items} hash table. These two arrays |
|
317 |
* allow to retrieve an Item from its index or, conversely, to get the index |
|
318 |
* of an Item from its value. Each Item stores an internal name in its |
|
319 |
* {@link Item#strVal1} field. |
|
320 |
*/ |
|
321 |
Item[] typeTable; |
|
322 |
||
323 |
/** |
|
324 |
* Number of elements in the {@link #typeTable} array. |
|
325 |
*/ |
|
326 |
private short typeCount; |
|
327 |
||
328 |
/** |
|
329 |
* The access flags of this class. |
|
330 |
*/ |
|
331 |
private int access; |
|
332 |
||
333 |
/** |
|
334 |
* The constant pool item that contains the internal name of this class. |
|
335 |
*/ |
|
336 |
private int name; |
|
337 |
||
338 |
/** |
|
339 |
* The internal name of this class. |
|
340 |
*/ |
|
341 |
String thisName; |
|
342 |
||
343 |
/** |
|
344 |
* The constant pool item that contains the signature of this class. |
|
345 |
*/ |
|
346 |
private int signature; |
|
347 |
||
348 |
/** |
|
349 |
* The constant pool item that contains the internal name of the super class |
|
350 |
* of this class. |
|
351 |
*/ |
|
352 |
private int superName; |
|
353 |
||
354 |
/** |
|
355 |
* Number of interfaces implemented or extended by this class or interface. |
|
356 |
*/ |
|
357 |
private int interfaceCount; |
|
358 |
||
359 |
/** |
|
360 |
* The interfaces implemented or extended by this class or interface. More |
|
361 |
* precisely, this array contains the indexes of the constant pool items |
|
362 |
* that contain the internal names of these interfaces. |
|
363 |
*/ |
|
364 |
private int[] interfaces; |
|
365 |
||
366 |
/** |
|
367 |
* The index of the constant pool item that contains the name of the source |
|
368 |
* file from which this class was compiled. |
|
369 |
*/ |
|
370 |
private int sourceFile; |
|
371 |
||
372 |
/** |
|
373 |
* The SourceDebug attribute of this class. |
|
374 |
*/ |
|
375 |
private ByteVector sourceDebug; |
|
376 |
||
377 |
/** |
|
378 |
* The constant pool item that contains the name of the enclosing class of |
|
379 |
* this class. |
|
380 |
*/ |
|
381 |
private int enclosingMethodOwner; |
|
382 |
||
383 |
/** |
|
384 |
* The constant pool item that contains the name and descriptor of the |
|
385 |
* enclosing method of this class. |
|
386 |
*/ |
|
387 |
private int enclosingMethod; |
|
388 |
||
389 |
/** |
|
390 |
* The runtime visible annotations of this class. |
|
391 |
*/ |
|
392 |
private AnnotationWriter anns; |
|
393 |
||
394 |
/** |
|
395 |
* The runtime invisible annotations of this class. |
|
396 |
*/ |
|
397 |
private AnnotationWriter ianns; |
|
398 |
||
399 |
/** |
|
400 |
* The non standard attributes of this class. |
|
401 |
*/ |
|
402 |
private Attribute attrs; |
|
403 |
||
404 |
/** |
|
405 |
* The number of entries in the InnerClasses attribute. |
|
406 |
*/ |
|
407 |
private int innerClassesCount; |
|
408 |
||
409 |
/** |
|
410 |
* The InnerClasses attribute. |
|
411 |
*/ |
|
412 |
private ByteVector innerClasses; |
|
413 |
||
414 |
/** |
|
415 |
* The fields of this class. These fields are stored in a linked list of |
|
416 |
* {@link FieldWriter} objects, linked to each other by their |
|
417 |
* {@link FieldWriter#next} field. This field stores the first element of |
|
418 |
* this list. |
|
419 |
*/ |
|
420 |
FieldWriter firstField; |
|
421 |
||
422 |
/** |
|
423 |
* The fields of this class. These fields are stored in a linked list of |
|
424 |
* {@link FieldWriter} objects, linked to each other by their |
|
425 |
* {@link FieldWriter#next} field. This field stores the last element of |
|
426 |
* this list. |
|
427 |
*/ |
|
428 |
FieldWriter lastField; |
|
429 |
||
430 |
/** |
|
431 |
* The methods of this class. These methods are stored in a linked list of |
|
432 |
* {@link MethodWriter} objects, linked to each other by their |
|
433 |
* {@link MethodWriter#next} field. This field stores the first element of |
|
434 |
* this list. |
|
435 |
*/ |
|
436 |
MethodWriter firstMethod; |
|
437 |
||
438 |
/** |
|
439 |
* The methods of this class. These methods are stored in a linked list of |
|
440 |
* {@link MethodWriter} objects, linked to each other by their |
|
441 |
* {@link MethodWriter#next} field. This field stores the last element of |
|
442 |
* this list. |
|
443 |
*/ |
|
444 |
MethodWriter lastMethod; |
|
445 |
||
446 |
/** |
|
447 |
* <tt>true</tt> if the maximum stack size and number of local variables |
|
448 |
* must be automatically computed. |
|
449 |
*/ |
|
450 |
private final boolean computeMaxs; |
|
451 |
||
452 |
/** |
|
453 |
* <tt>true</tt> if the stack map frames must be recomputed from scratch. |
|
454 |
*/ |
|
455 |
private final boolean computeFrames; |
|
456 |
||
457 |
/** |
|
458 |
* <tt>true</tt> if the stack map tables of this class are invalid. The |
|
459 |
* {@link MethodWriter#resizeInstructions} method cannot transform existing |
|
460 |
* stack map tables, and so produces potentially invalid classes when it is |
|
461 |
* executed. In this case the class is reread and rewritten with the |
|
462 |
* {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize |
|
463 |
* stack map tables when this option is used). |
|
464 |
*/ |
|
465 |
boolean invalidFrames; |
|
466 |
||
467 |
// ------------------------------------------------------------------------ |
|
468 |
// Static initializer |
|
469 |
// ------------------------------------------------------------------------ |
|
470 |
||
471 |
/** |
|
472 |
* Computes the instruction types of JVM opcodes. |
|
473 |
*/ |
|
474 |
static { |
|
475 |
int i; |
|
476 |
byte[] b = new byte[220]; |
|
477 |
String s = "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD" |
|
478 |
+ "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |
|
479 |
+ "AAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAA" |
|
480 |
+ "AAAAGGGGGGGHAFBFAAFFAAQPIIJJIIIIIIIIIIIIIIIIII"; |
|
481 |
for (i = 0; i < b.length; ++i) { |
|
482 |
b[i] = (byte) (s.charAt(i) - 'A'); |
|
483 |
} |
|
484 |
TYPE = b; |
|
485 |
||
486 |
// code to generate the above string |
|
487 |
// |
|
488 |
// // SBYTE_INSN instructions |
|
489 |
// b[Constants.NEWARRAY] = SBYTE_INSN; |
|
490 |
// b[Constants.BIPUSH] = SBYTE_INSN; |
|
491 |
// |
|
492 |
// // SHORT_INSN instructions |
|
493 |
// b[Constants.SIPUSH] = SHORT_INSN; |
|
494 |
// |
|
495 |
// // (IMPL)VAR_INSN instructions |
|
496 |
// b[Constants.RET] = VAR_INSN; |
|
497 |
// for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) { |
|
498 |
// b[i] = VAR_INSN; |
|
499 |
// } |
|
500 |
// for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) { |
|
501 |
// b[i] = VAR_INSN; |
|
502 |
// } |
|
503 |
// for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3 |
|
504 |
// b[i] = IMPLVAR_INSN; |
|
505 |
// } |
|
506 |
// for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3 |
|
507 |
// b[i] = IMPLVAR_INSN; |
|
508 |
// } |
|
509 |
// |
|
510 |
// // TYPE_INSN instructions |
|
511 |
// b[Constants.NEW] = TYPE_INSN; |
|
512 |
// b[Constants.ANEWARRAY] = TYPE_INSN; |
|
513 |
// b[Constants.CHECKCAST] = TYPE_INSN; |
|
514 |
// b[Constants.INSTANCEOF] = TYPE_INSN; |
|
515 |
// |
|
516 |
// // (Set)FIELDORMETH_INSN instructions |
|
517 |
// for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) { |
|
518 |
// b[i] = FIELDORMETH_INSN; |
|
519 |
// } |
|
520 |
// b[Constants.INVOKEINTERFACE] = ITFMETH_INSN; |
|
521 |
// |
|
522 |
// // LABEL(W)_INSN instructions |
|
523 |
// for (i = Constants.IFEQ; i <= Constants.JSR; ++i) { |
|
524 |
// b[i] = LABEL_INSN; |
|
525 |
// } |
|
526 |
// b[Constants.IFNULL] = LABEL_INSN; |
|
527 |
// b[Constants.IFNONNULL] = LABEL_INSN; |
|
528 |
// b[200] = LABELW_INSN; // GOTO_W |
|
529 |
// b[201] = LABELW_INSN; // JSR_W |
|
530 |
// // temporary opcodes used internally by ASM - see Label and |
|
531 |
// MethodWriter |
|
532 |
// for (i = 202; i < 220; ++i) { |
|
533 |
// b[i] = LABEL_INSN; |
|
534 |
// } |
|
535 |
// |
|
536 |
// // LDC(_W) instructions |
|
537 |
// b[Constants.LDC] = LDC_INSN; |
|
538 |
// b[19] = LDCW_INSN; // LDC_W |
|
539 |
// b[20] = LDCW_INSN; // LDC2_W |
|
540 |
// |
|
541 |
// // special instructions |
|
542 |
// b[Constants.IINC] = IINC_INSN; |
|
543 |
// b[Constants.TABLESWITCH] = TABL_INSN; |
|
544 |
// b[Constants.LOOKUPSWITCH] = LOOK_INSN; |
|
545 |
// b[Constants.MULTIANEWARRAY] = MANA_INSN; |
|
546 |
// b[196] = WIDE_INSN; // WIDE |
|
547 |
// |
|
548 |
// for (i = 0; i < b.length; ++i) { |
|
549 |
// System.err.print((char)('A' + b[i])); |
|
550 |
// } |
|
551 |
// System.err.println(); |
|
552 |
} |
|
553 |
||
554 |
// ------------------------------------------------------------------------ |
|
555 |
// Constructor |
|
556 |
// ------------------------------------------------------------------------ |
|
557 |
||
558 |
/** |
|
559 |
* Constructs a new {@link ClassWriter} object. |
|
560 |
* |
|
561 |
* @param flags option flags that can be used to modify the default behavior |
|
562 |
* of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}. |
|
563 |
*/ |
|
564 |
public ClassWriter(final int flags) { |
|
565 |
index = 1; |
|
566 |
pool = new ByteVector(); |
|
567 |
items = new Item[256]; |
|
568 |
threshold = (int) (0.75d * items.length); |
|
569 |
key = new Item(); |
|
570 |
key2 = new Item(); |
|
571 |
key3 = new Item(); |
|
572 |
this.computeMaxs = (flags & COMPUTE_MAXS) != 0; |
|
573 |
this.computeFrames = (flags & COMPUTE_FRAMES) != 0; |
|
574 |
} |
|
575 |
||
576 |
/** |
|
577 |
* Constructs a new {@link ClassWriter} object and enables optimizations for |
|
578 |
* "mostly add" bytecode transformations. These optimizations are the |
|
579 |
* following: |
|
580 |
* |
|
581 |
* <ul> <li>The constant pool from the original class is copied as is in |
|
582 |
* the new class, which saves time. New constant pool entries will be added |
|
583 |
* at the end if necessary, but unused constant pool entries <i>won't be |
|
584 |
* removed</i>.</li> <li>Methods that are not transformed are copied as |
|
585 |
* is in the new class, directly from the original class bytecode (i.e. |
|
586 |
* without emitting visit events for all the method instructions), which |
|
587 |
* saves a <i>lot</i> of time. Untransformed methods are detected by the |
|
588 |
* fact that the {@link ClassReader} receives {@link MethodVisitor} objects |
|
589 |
* that come from a {@link ClassWriter} (and not from a custom |
|
590 |
* {@link ClassAdapter} or any other {@link ClassVisitor} instance).</li> |
|
591 |
* </ul> |
|
592 |
* |
|
593 |
* @param classReader the {@link ClassReader} used to read the original |
|
594 |
* class. It will be used to copy the entire constant pool from the |
|
595 |
* original class and also to copy other fragments of original |
|
596 |
* bytecode where applicable. |
|
597 |
* @param flags option flags that can be used to modify the default behavior |
|
598 |
* of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}. |
|
599 |
*/ |
|
600 |
public ClassWriter(final ClassReader classReader, final int flags) { |
|
601 |
this(flags); |
|
602 |
classReader.copyPool(this); |
|
603 |
this.cr = classReader; |
|
604 |
} |
|
605 |
||
606 |
// ------------------------------------------------------------------------ |
|
607 |
// Implementation of the ClassVisitor interface |
|
608 |
// ------------------------------------------------------------------------ |
|
609 |
||
610 |
public void visit( |
|
611 |
final int version, |
|
612 |
final int access, |
|
613 |
final String name, |
|
614 |
final String signature, |
|
615 |
final String superName, |
|
616 |
final String[] interfaces) |
|
617 |
{ |
|
618 |
this.version = version; |
|
619 |
this.access = access; |
|
620 |
this.name = newClass(name); |
|
621 |
thisName = name; |
|
622 |
if (ClassReader.SIGNATURES && signature != null) { |
|
623 |
this.signature = newUTF8(signature); |
|
624 |
} |
|
625 |
this.superName = superName == null ? 0 : newClass(superName); |
|
626 |
if (interfaces != null && interfaces.length > 0) { |
|
627 |
interfaceCount = interfaces.length; |
|
628 |
this.interfaces = new int[interfaceCount]; |
|
629 |
for (int i = 0; i < interfaceCount; ++i) { |
|
630 |
this.interfaces[i] = newClass(interfaces[i]); |
|
631 |
} |
|
632 |
} |
|
633 |
} |
|
634 |
||
635 |
public void visitSource(final String file, final String debug) { |
|
636 |
if (file != null) { |
|
637 |
sourceFile = newUTF8(file); |
|
638 |
} |
|
639 |
if (debug != null) { |
|
640 |
sourceDebug = new ByteVector().putUTF8(debug); |
|
641 |
} |
|
642 |
} |
|
643 |
||
644 |
public void visitOuterClass( |
|
645 |
final String owner, |
|
646 |
final String name, |
|
647 |
final String desc) |
|
648 |
{ |
|
649 |
enclosingMethodOwner = newClass(owner); |
|
650 |
if (name != null && desc != null) { |
|
651 |
enclosingMethod = newNameType(name, desc); |
|
652 |
} |
|
653 |
} |
|
654 |
||
655 |
public AnnotationVisitor visitAnnotation( |
|
656 |
final String desc, |
|
657 |
final boolean visible) |
|
658 |
{ |
|
659 |
if (!ClassReader.ANNOTATIONS) { |
|
660 |
return null; |
|
661 |
} |
|
662 |
ByteVector bv = new ByteVector(); |
|
663 |
// write type, and reserve space for values count |
|
664 |
bv.putShort(newUTF8(desc)).putShort(0); |
|
665 |
AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2); |
|
666 |
if (visible) { |
|
667 |
aw.next = anns; |
|
668 |
anns = aw; |
|
669 |
} else { |
|
670 |
aw.next = ianns; |
|
671 |
ianns = aw; |
|
672 |
} |
|
673 |
return aw; |
|
674 |
} |
|
675 |
||
676 |
public void visitAttribute(final Attribute attr) { |
|
677 |
attr.next = attrs; |
|
678 |
attrs = attr; |
|
679 |
} |
|
680 |
||
681 |
public void visitInnerClass( |
|
682 |
final String name, |
|
683 |
final String outerName, |
|
684 |
final String innerName, |
|
685 |
final int access) |
|
686 |
{ |
|
687 |
if (innerClasses == null) { |
|
688 |
innerClasses = new ByteVector(); |
|
689 |
} |
|
690 |
++innerClassesCount; |
|
691 |
innerClasses.putShort(name == null ? 0 : newClass(name)); |
|
692 |
innerClasses.putShort(outerName == null ? 0 : newClass(outerName)); |
|
693 |
innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName)); |
|
694 |
innerClasses.putShort(access); |
|
695 |
} |
|
696 |
||
697 |
public FieldVisitor visitField( |
|
698 |
final int access, |
|
699 |
final String name, |
|
700 |
final String desc, |
|
701 |
final String signature, |
|
702 |
final Object value) |
|
703 |
{ |
|
704 |
return new FieldWriter(this, access, name, desc, signature, value); |
|
705 |
} |
|
706 |
||
707 |
public MethodVisitor visitMethod( |
|
708 |
final int access, |
|
709 |
final String name, |
|
710 |
final String desc, |
|
711 |
final String signature, |
|
712 |
final String[] exceptions) |
|
713 |
{ |
|
714 |
return new MethodWriter(this, |
|
715 |
access, |
|
716 |
name, |
|
717 |
desc, |
|
718 |
signature, |
|
719 |
exceptions, |
|
720 |
computeMaxs, |
|
721 |
computeFrames); |
|
722 |
} |
|
723 |
||
724 |
public void visitEnd() { |
|
725 |
} |
|
726 |
||
727 |
// ------------------------------------------------------------------------ |
|
728 |
// Other public methods |
|
729 |
// ------------------------------------------------------------------------ |
|
730 |
||
731 |
/** |
|
732 |
* Returns the bytecode of the class that was build with this class writer. |
|
733 |
* |
|
734 |
* @return the bytecode of the class that was build with this class writer. |
|
735 |
*/ |
|
736 |
public byte[] toByteArray() { |
|
737 |
// computes the real size of the bytecode of this class |
|
738 |
int size = 24 + 2 * interfaceCount; |
|
739 |
int nbFields = 0; |
|
740 |
FieldWriter fb = firstField; |
|
741 |
while (fb != null) { |
|
742 |
++nbFields; |
|
743 |
size += fb.getSize(); |
|
744 |
fb = fb.next; |
|
745 |
} |
|
746 |
int nbMethods = 0; |
|
747 |
MethodWriter mb = firstMethod; |
|
748 |
while (mb != null) { |
|
749 |
++nbMethods; |
|
750 |
size += mb.getSize(); |
|
751 |
mb = mb.next; |
|
752 |
} |
|
753 |
int attributeCount = 0; |
|
754 |
if (ClassReader.SIGNATURES && signature != 0) { |
|
755 |
++attributeCount; |
|
756 |
size += 8; |
|
757 |
newUTF8("Signature"); |
|
758 |
} |
|
759 |
if (sourceFile != 0) { |
|
760 |
++attributeCount; |
|
761 |
size += 8; |
|
762 |
newUTF8("SourceFile"); |
|
763 |
} |
|
764 |
if (sourceDebug != null) { |
|
765 |
++attributeCount; |
|
766 |
size += sourceDebug.length + 4; |
|
767 |
newUTF8("SourceDebugExtension"); |
|
768 |
} |
|
769 |
if (enclosingMethodOwner != 0) { |
|
770 |
++attributeCount; |
|
771 |
size += 10; |
|
772 |
newUTF8("EnclosingMethod"); |
|
773 |
} |
|
774 |
if ((access & Opcodes.ACC_DEPRECATED) != 0) { |
|
775 |
++attributeCount; |
|
776 |
size += 6; |
|
777 |
newUTF8("Deprecated"); |
|
778 |
} |
|
779 |
if ((access & Opcodes.ACC_SYNTHETIC) != 0 |
|
780 |
&& (version & 0xffff) < Opcodes.V1_5) |
|
781 |
{ |
|
782 |
++attributeCount; |
|
783 |
size += 6; |
|
784 |
newUTF8("Synthetic"); |
|
785 |
} |
|
786 |
if (innerClasses != null) { |
|
787 |
++attributeCount; |
|
788 |
size += 8 + innerClasses.length; |
|
789 |
newUTF8("InnerClasses"); |
|
790 |
} |
|
791 |
if (ClassReader.ANNOTATIONS && anns != null) { |
|
792 |
++attributeCount; |
|
793 |
size += 8 + anns.getSize(); |
|
794 |
newUTF8("RuntimeVisibleAnnotations"); |
|
795 |
} |
|
796 |
if (ClassReader.ANNOTATIONS && ianns != null) { |
|
797 |
++attributeCount; |
|
798 |
size += 8 + ianns.getSize(); |
|
799 |
newUTF8("RuntimeInvisibleAnnotations"); |
|
800 |
} |
|
801 |
if (attrs != null) { |
|
802 |
attributeCount += attrs.getCount(); |
|
803 |
size += attrs.getSize(this, null, 0, -1, -1); |
|
804 |
} |
|
805 |
size += pool.length; |
|
806 |
// allocates a byte vector of this size, in order to avoid unnecessary |
|
807 |
// arraycopy operations in the ByteVector.enlarge() method |
|
808 |
ByteVector out = new ByteVector(size); |
|
809 |
out.putInt(0xCAFEBABE).putInt(version); |
|
810 |
out.putShort(index).putByteArray(pool.data, 0, pool.length); |
|
811 |
out.putShort(access).putShort(name).putShort(superName); |
|
812 |
out.putShort(interfaceCount); |
|
813 |
for (int i = 0; i < interfaceCount; ++i) { |
|
814 |
out.putShort(interfaces[i]); |
|
815 |
} |
|
816 |
out.putShort(nbFields); |
|
817 |
fb = firstField; |
|
818 |
while (fb != null) { |
|
819 |
fb.put(out); |
|
820 |
fb = fb.next; |
|
821 |
} |
|
822 |
out.putShort(nbMethods); |
|
823 |
mb = firstMethod; |
|
824 |
while (mb != null) { |
|
825 |
mb.put(out); |
|
826 |
mb = mb.next; |
|
827 |
} |
|
828 |
out.putShort(attributeCount); |
|
829 |
if (ClassReader.SIGNATURES && signature != 0) { |
|
830 |
out.putShort(newUTF8("Signature")).putInt(2).putShort(signature); |
|
831 |
} |
|
832 |
if (sourceFile != 0) { |
|
833 |
out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile); |
|
834 |
} |
|
835 |
if (sourceDebug != null) { |
|
836 |
int len = sourceDebug.length - 2; |
|
837 |
out.putShort(newUTF8("SourceDebugExtension")).putInt(len); |
|
838 |
out.putByteArray(sourceDebug.data, 2, len); |
|
839 |
} |
|
840 |
if (enclosingMethodOwner != 0) { |
|
841 |
out.putShort(newUTF8("EnclosingMethod")).putInt(4); |
|
842 |
out.putShort(enclosingMethodOwner).putShort(enclosingMethod); |
|
843 |
} |
|
844 |
if ((access & Opcodes.ACC_DEPRECATED) != 0) { |
|
845 |
out.putShort(newUTF8("Deprecated")).putInt(0); |
|
846 |
} |
|
847 |
if ((access & Opcodes.ACC_SYNTHETIC) != 0 |
|
848 |
&& (version & 0xffff) < Opcodes.V1_5) |
|
849 |
{ |
|
850 |
out.putShort(newUTF8("Synthetic")).putInt(0); |
|
851 |
} |
|
852 |
if (innerClasses != null) { |
|
853 |
out.putShort(newUTF8("InnerClasses")); |
|
854 |
out.putInt(innerClasses.length + 2).putShort(innerClassesCount); |
|
855 |
out.putByteArray(innerClasses.data, 0, innerClasses.length); |
|
856 |
} |
|
857 |
if (ClassReader.ANNOTATIONS && anns != null) { |
|
858 |
out.putShort(newUTF8("RuntimeVisibleAnnotations")); |
|
859 |
anns.put(out); |
|
860 |
} |
|
861 |
if (ClassReader.ANNOTATIONS && ianns != null) { |
|
862 |
out.putShort(newUTF8("RuntimeInvisibleAnnotations")); |
|
863 |
ianns.put(out); |
|
864 |
} |
|
865 |
if (attrs != null) { |
|
866 |
attrs.put(this, null, 0, -1, -1, out); |
|
867 |
} |
|
868 |
if (invalidFrames) { |
|
869 |
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES); |
|
870 |
new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES); |
|
871 |
return cw.toByteArray(); |
|
872 |
} |
|
873 |
return out.data; |
|
874 |
} |
|
875 |
||
876 |
// ------------------------------------------------------------------------ |
|
877 |
// Utility methods: constant pool management |
|
878 |
// ------------------------------------------------------------------------ |
|
879 |
||
880 |
/** |
|
881 |
* Adds a number or string constant to the constant pool of the class being |
|
882 |
* build. Does nothing if the constant pool already contains a similar item. |
|
883 |
* |
|
884 |
* @param cst the value of the constant to be added to the constant pool. |
|
885 |
* This parameter must be an {@link Integer}, a {@link Float}, a |
|
886 |
* {@link Long}, a {@link Double}, a {@link String} or a |
|
887 |
* {@link Type}. |
|
888 |
* @return a new or already existing constant item with the given value. |
|
889 |
*/ |
|
890 |
Item newConstItem(final Object cst) { |
|
891 |
if (cst instanceof Integer) { |
|
892 |
int val = ((Integer) cst).intValue(); |
|
893 |
return newInteger(val); |
|
894 |
} else if (cst instanceof Byte) { |
|
895 |
int val = ((Byte) cst).intValue(); |
|
896 |
return newInteger(val); |
|
897 |
} else if (cst instanceof Character) { |
|
898 |
int val = ((Character) cst).charValue(); |
|
899 |
return newInteger(val); |
|
900 |
} else if (cst instanceof Short) { |
|
901 |
int val = ((Short) cst).intValue(); |
|
902 |
return newInteger(val); |
|
903 |
} else if (cst instanceof Boolean) { |
|
904 |
int val = ((Boolean) cst).booleanValue() ? 1 : 0; |
|
905 |
return newInteger(val); |
|
906 |
} else if (cst instanceof Float) { |
|
907 |
float val = ((Float) cst).floatValue(); |
|
908 |
return newFloat(val); |
|
909 |
} else if (cst instanceof Long) { |
|
910 |
long val = ((Long) cst).longValue(); |
|
911 |
return newLong(val); |
|
912 |
} else if (cst instanceof Double) { |
|
913 |
double val = ((Double) cst).doubleValue(); |
|
914 |
return newDouble(val); |
|
915 |
} else if (cst instanceof String) { |
|
916 |
return newString((String) cst); |
|
917 |
} else if (cst instanceof Type) { |
|
918 |
Type t = (Type) cst; |
|
919 |
return newClassItem(t.getSort() == Type.OBJECT |
|
920 |
? t.getInternalName() |
|
921 |
: t.getDescriptor()); |
|
922 |
} else { |
|
923 |
throw new IllegalArgumentException("value " + cst); |
|
924 |
} |
|
925 |
} |
|
926 |
||
927 |
/** |
|
928 |
* Adds a number or string constant to the constant pool of the class being |
|
929 |
* build. Does nothing if the constant pool already contains a similar item. |
|
930 |
* <i>This method is intended for {@link Attribute} sub classes, and is |
|
931 |
* normally not needed by class generators or adapters.</i> |
|
932 |
* |
|
933 |
* @param cst the value of the constant to be added to the constant pool. |
|
934 |
* This parameter must be an {@link Integer}, a {@link Float}, a |
|
935 |
* {@link Long}, a {@link Double} or a {@link String}. |
|
936 |
* @return the index of a new or already existing constant item with the |
|
937 |
* given value. |
|
938 |
*/ |
|
939 |
public int newConst(final Object cst) { |
|
940 |
return newConstItem(cst).index; |
|
941 |
} |
|
942 |
||
943 |
/** |
|
944 |
* Adds an UTF8 string to the constant pool of the class being build. Does |
|
945 |
* nothing if the constant pool already contains a similar item. <i>This |
|
946 |
* method is intended for {@link Attribute} sub classes, and is normally not |
|
947 |
* needed by class generators or adapters.</i> |
|
948 |
* |
|
949 |
* @param value the String value. |
|
950 |
* @return the index of a new or already existing UTF8 item. |
|
951 |
*/ |
|
952 |
public int newUTF8(final String value) { |
|
953 |
key.set(UTF8, value, null, null); |
|
954 |
Item result = get(key); |
|
955 |
if (result == null) { |
|
956 |
pool.putByte(UTF8).putUTF8(value); |
|
957 |
result = new Item(index++, key); |
|
958 |
put(result); |
|
959 |
} |
|
960 |
return result.index; |
|
961 |
} |
|
962 |
||
963 |
/** |
|
964 |
* Adds a class reference to the constant pool of the class being build. |
|
965 |
* Does nothing if the constant pool already contains a similar item. |
|
966 |
* <i>This method is intended for {@link Attribute} sub classes, and is |
|
967 |
* normally not needed by class generators or adapters.</i> |
|
968 |
* |
|
969 |
* @param value the internal name of the class. |
|
970 |
* @return a new or already existing class reference item. |
|
971 |
*/ |
|
972 |
Item newClassItem(final String value) { |
|
973 |
key2.set(CLASS, value, null, null); |
|
974 |
Item result = get(key2); |
|
975 |
if (result == null) { |
|
976 |
pool.put12(CLASS, newUTF8(value)); |
|
977 |
result = new Item(index++, key2); |
|
978 |
put(result); |
|
979 |
} |
|
980 |
return result; |
|
981 |
} |
|
982 |
||
983 |
/** |
|
984 |
* Adds a class reference to the constant pool of the class being build. |
|
985 |
* Does nothing if the constant pool already contains a similar item. |
|
986 |
* <i>This method is intended for {@link Attribute} sub classes, and is |
|
987 |
* normally not needed by class generators or adapters.</i> |
|
988 |
* |
|
989 |
* @param value the internal name of the class. |
|
990 |
* @return the index of a new or already existing class reference item. |
|
991 |
*/ |
|
992 |
public int newClass(final String value) { |
|
993 |
return newClassItem(value).index; |
|
994 |
} |
|
995 |
||
996 |
/** |
|
997 |
* Adds a field reference to the constant pool of the class being build. |
|
998 |
* Does nothing if the constant pool already contains a similar item. |
|
999 |
* |
|
1000 |
* @param owner the internal name of the field's owner class. |
|
1001 |
* @param name the field's name. |
|
1002 |
* @param desc the field's descriptor. |
|
1003 |
* @return a new or already existing field reference item. |
|
1004 |
*/ |
|
1005 |
Item newFieldItem(final String owner, final String name, final String desc) |
|
1006 |
{ |
|
1007 |
key3.set(FIELD, owner, name, desc); |
|
1008 |
Item result = get(key3); |
|
1009 |
if (result == null) { |
|
1010 |
put122(FIELD, newClass(owner), newNameType(name, desc)); |
|
1011 |
result = new Item(index++, key3); |
|
1012 |
put(result); |
|
1013 |
} |
|
1014 |
return result; |
|
1015 |
} |
|
1016 |
||
1017 |
/** |
|
1018 |
* Adds a field reference to the constant pool of the class being build. |
|
1019 |
* Does nothing if the constant pool already contains a similar item. |
|
1020 |
* <i>This method is intended for {@link Attribute} sub classes, and is |
|
1021 |
* normally not needed by class generators or adapters.</i> |
|
1022 |
* |
|
1023 |
* @param owner the internal name of the field's owner class. |
|
1024 |
* @param name the field's name. |
|
1025 |
* @param desc the field's descriptor. |
|
1026 |
* @return the index of a new or already existing field reference item. |
|
1027 |
*/ |
|
1028 |
public int newField(final String owner, final String name, final String desc) |
|
1029 |
{ |
|
1030 |
return newFieldItem(owner, name, desc).index; |
|
1031 |
} |
|
1032 |
||
1033 |
/** |
|
1034 |
* Adds a method reference to the constant pool of the class being build. |
|
1035 |
* Does nothing if the constant pool already contains a similar item. |
|
1036 |
* |
|
1037 |
* @param owner the internal name of the method's owner class. |
|
1038 |
* @param name the method's name. |
|
1039 |
* @param desc the method's descriptor. |
|
1040 |
* @param itf <tt>true</tt> if <tt>owner</tt> is an interface. |
|
1041 |
* @return a new or already existing method reference item. |
|
1042 |
*/ |
|
1043 |
Item newMethodItem( |
|
1044 |
final String owner, |
|
1045 |
final String name, |
|
1046 |
final String desc, |
|
1047 |
final boolean itf) |
|
1048 |
{ |
|
1049 |
int type = itf ? IMETH : METH; |
|
1050 |
key3.set(type, owner, name, desc); |
|
1051 |
Item result = get(key3); |
|
1052 |
if (result == null) { |
|
1053 |
put122(type, newClass(owner), newNameType(name, desc)); |
|
1054 |
result = new Item(index++, key3); |
|
1055 |
put(result); |
|
1056 |
} |
|
1057 |
return result; |
|
1058 |
} |
|
1059 |
||
1060 |
/** |
|
1061 |
* Adds a method reference to the constant pool of the class being build. |
|
1062 |
* Does nothing if the constant pool already contains a similar item. |
|
1063 |
* <i>This method is intended for {@link Attribute} sub classes, and is |
|
1064 |
* normally not needed by class generators or adapters.</i> |
|
1065 |
* |
|
1066 |
* @param owner the internal name of the method's owner class. |
|
1067 |
* @param name the method's name. |
|
1068 |
* @param desc the method's descriptor. |
|
1069 |
* @param itf <tt>true</tt> if <tt>owner</tt> is an interface. |
|
1070 |
* @return the index of a new or already existing method reference item. |
|
1071 |
*/ |
|
1072 |
public int newMethod( |
|
1073 |
final String owner, |
|
1074 |
final String name, |
|
1075 |
final String desc, |
|
1076 |
final boolean itf) |
|
1077 |
{ |
|
1078 |
return newMethodItem(owner, name, desc, itf).index; |
|
1079 |
} |
|
1080 |
||
1081 |
/** |
|
1082 |
* Adds an integer to the constant pool of the class being build. Does |
|
1083 |
* nothing if the constant pool already contains a similar item. |
|
1084 |
* |
|
1085 |
* @param value the int value. |
|
1086 |
* @return a new or already existing int item. |
|
1087 |
*/ |
|
1088 |
Item newInteger(final int value) { |
|
1089 |
key.set(value); |
|
1090 |
Item result = get(key); |
|
1091 |
if (result == null) { |
|
1092 |
pool.putByte(INT).putInt(value); |
|
1093 |
result = new Item(index++, key); |
|
1094 |
put(result); |
|
1095 |
} |
|
1096 |
return result; |
|
1097 |
} |
|
1098 |
||
1099 |
/** |
|
1100 |
* Adds a float to the constant pool of the class being build. Does nothing |
|
1101 |
* if the constant pool already contains a similar item. |
|
1102 |
* |
|
1103 |
* @param value the float value. |
|
1104 |
* @return a new or already existing float item. |
|
1105 |
*/ |
|
1106 |
Item newFloat(final float value) { |
|
1107 |
key.set(value); |
|
1108 |
Item result = get(key); |
|
1109 |
if (result == null) { |
|
1110 |
pool.putByte(FLOAT).putInt(key.intVal); |
|
1111 |
result = new Item(index++, key); |
|
1112 |
put(result); |
|
1113 |
} |
|
1114 |
return result; |
|
1115 |
} |
|
1116 |
||
1117 |
/** |
|
1118 |
* Adds a long to the constant pool of the class being build. Does nothing |
|
1119 |
* if the constant pool already contains a similar item. |
|
1120 |
* |
|
1121 |
* @param value the long value. |
|
1122 |
* @return a new or already existing long item. |
|
1123 |
*/ |
|
1124 |
Item newLong(final long value) { |
|
1125 |
key.set(value); |
|
1126 |
Item result = get(key); |
|
1127 |
if (result == null) { |
|
1128 |
pool.putByte(LONG).putLong(value); |
|
1129 |
result = new Item(index, key); |
|
1130 |
put(result); |
|
1131 |
index += 2; |
|
1132 |
} |
|
1133 |
return result; |
|
1134 |
} |
|
1135 |
||
1136 |
/** |
|
1137 |
* Adds a double to the constant pool of the class being build. Does nothing |
|
1138 |
* if the constant pool already contains a similar item. |
|
1139 |
* |
|
1140 |
* @param value the double value. |
|
1141 |
* @return a new or already existing double item. |
|
1142 |
*/ |
|
1143 |
Item newDouble(final double value) { |
|
1144 |
key.set(value); |
|
1145 |
Item result = get(key); |
|
1146 |
if (result == null) { |
|
1147 |
pool.putByte(DOUBLE).putLong(key.longVal); |
|
1148 |
result = new Item(index, key); |
|
1149 |
put(result); |
|
1150 |
index += 2; |
|
1151 |
} |
|
1152 |
return result; |
|
1153 |
} |
|
1154 |
||
1155 |
/** |
|
1156 |
* Adds a string to the constant pool of the class being build. Does nothing |
|
1157 |
* if the constant pool already contains a similar item. |
|
1158 |
* |
|
1159 |
* @param value the String value. |
|
1160 |
* @return a new or already existing string item. |
|
1161 |
*/ |
|
1162 |
private Item newString(final String value) { |
|
1163 |
key2.set(STR, value, null, null); |
|
1164 |
Item result = get(key2); |
|
1165 |
if (result == null) { |
|
1166 |
pool.put12(STR, newUTF8(value)); |
|
1167 |
result = new Item(index++, key2); |
|
1168 |
put(result); |
|
1169 |
} |
|
1170 |
return result; |
|
1171 |
} |
|
1172 |
||
1173 |
/** |
|
1174 |
* Adds a name and type to the constant pool of the class being build. Does |
|
1175 |
* nothing if the constant pool already contains a similar item. <i>This |
|
1176 |
* method is intended for {@link Attribute} sub classes, and is normally not |
|
1177 |
* needed by class generators or adapters.</i> |
|
1178 |
* |
|
1179 |
* @param name a name. |
|
1180 |
* @param desc a type descriptor. |
|
1181 |
* @return the index of a new or already existing name and type item. |
|
1182 |
*/ |
|
1183 |
public int newNameType(final String name, final String desc) { |
|
1184 |
key2.set(NAME_TYPE, name, desc, null); |
|
1185 |
Item result = get(key2); |
|
1186 |
if (result == null) { |
|
1187 |
put122(NAME_TYPE, newUTF8(name), newUTF8(desc)); |
|
1188 |
result = new Item(index++, key2); |
|
1189 |
put(result); |
|
1190 |
} |
|
1191 |
return result.index; |
|
1192 |
} |
|
1193 |
||
1194 |
/** |
|
1195 |
* Adds the given internal name to {@link #typeTable} and returns its index. |
|
1196 |
* Does nothing if the type table already contains this internal name. |
|
1197 |
* |
|
1198 |
* @param type the internal name to be added to the type table. |
|
1199 |
* @return the index of this internal name in the type table. |
|
1200 |
*/ |
|
1201 |
int addType(final String type) { |
|
1202 |
key.set(TYPE_NORMAL, type, null, null); |
|
1203 |
Item result = get(key); |
|
1204 |
if (result == null) { |
|
1205 |
result = addType(key); |
|
1206 |
} |
|
1207 |
return result.index; |
|
1208 |
} |
|
1209 |
||
1210 |
/** |
|
1211 |
* Adds the given "uninitialized" type to {@link #typeTable} and returns its |
|
1212 |
* index. This method is used for UNINITIALIZED types, made of an internal |
|
1213 |
* name and a bytecode offset. |
|
1214 |
* |
|
1215 |
* @param type the internal name to be added to the type table. |
|
1216 |
* @param offset the bytecode offset of the NEW instruction that created |
|
1217 |
* this UNINITIALIZED type value. |
|
1218 |
* @return the index of this internal name in the type table. |
|
1219 |
*/ |
|
1220 |
int addUninitializedType(final String type, final int offset) { |
|
1221 |
key.type = TYPE_UNINIT; |
|
1222 |
key.intVal = offset; |
|
1223 |
key.strVal1 = type; |
|
1224 |
key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset); |
|
1225 |
Item result = get(key); |
|
1226 |
if (result == null) { |
|
1227 |
result = addType(key); |
|
1228 |
} |
|
1229 |
return result.index; |
|
1230 |
} |
|
1231 |
||
1232 |
/** |
|
1233 |
* Adds the given Item to {@link #typeTable}. |
|
1234 |
* |
|
1235 |
* @param item the value to be added to the type table. |
|
1236 |
* @return the added Item, which a new Item instance with the same value as |
|
1237 |
* the given Item. |
|
1238 |
*/ |
|
1239 |
private Item addType(final Item item) { |
|
1240 |
++typeCount; |
|
1241 |
Item result = new Item(typeCount, key); |
|
1242 |
put(result); |
|
1243 |
if (typeTable == null) { |
|
1244 |
typeTable = new Item[16]; |
|
1245 |
} |
|
1246 |
if (typeCount == typeTable.length) { |
|
1247 |
Item[] newTable = new Item[2 * typeTable.length]; |
|
1248 |
System.arraycopy(typeTable, 0, newTable, 0, typeTable.length); |
|
1249 |
typeTable = newTable; |
|
1250 |
} |
|
1251 |
typeTable[typeCount] = result; |
|
1252 |
return result; |
|
1253 |
} |
|
1254 |
||
1255 |
/** |
|
1256 |
* Returns the index of the common super type of the two given types. This |
|
1257 |
* method calls {@link #getCommonSuperClass} and caches the result in the |
|
1258 |
* {@link #items} hash table to speedup future calls with the same |
|
1259 |
* parameters. |
|
1260 |
* |
|
1261 |
* @param type1 index of an internal name in {@link #typeTable}. |
|
1262 |
* @param type2 index of an internal name in {@link #typeTable}. |
|
1263 |
* @return the index of the common super type of the two given types. |
|
1264 |
*/ |
|
1265 |
int getMergedType(final int type1, final int type2) { |
|
1266 |
key2.type = TYPE_MERGED; |
|
1267 |
key2.longVal = type1 | (((long) type2) << 32); |
|
1268 |
key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2); |
|
1269 |
Item result = get(key2); |
|
1270 |
if (result == null) { |
|
1271 |
String t = typeTable[type1].strVal1; |
|
1272 |
String u = typeTable[type2].strVal1; |
|
1273 |
key2.intVal = addType(getCommonSuperClass(t, u)); |
|
1274 |
result = new Item((short) 0, key2); |
|
1275 |
put(result); |
|
1276 |
} |
|
1277 |
return result.intVal; |
|
1278 |
} |
|
1279 |
||
1280 |
/** |
|
1281 |
* Returns the common super type of the two given types. The default |
|
1282 |
* implementation of this method <i>loads<i> the two given classes and uses |
|
1283 |
* the java.lang.Class methods to find the common super class. It can be |
|
1284 |
* overridden to compute this common super type in other ways, in particular |
|
1285 |
* without actually loading any class, or to take into account the class |
|
1286 |
* that is currently being generated by this ClassWriter, which can of |
|
1287 |
* course not be loaded since it is under construction. |
|
1288 |
* |
|
1289 |
* @param type1 the internal name of a class. |
|
1290 |
* @param type2 the internal name of another class. |
|
1291 |
* @return the internal name of the common super class of the two given |
|
1292 |
* classes. |
|
1293 |
*/ |
|
1294 |
protected String getCommonSuperClass(final String type1, final String type2) |
|
1295 |
{ |
|
1296 |
Class c, d; |
|
1297 |
try { |
|
1298 |
c = Class.forName(type1.replace('/', '.')); |
|
1299 |
d = Class.forName(type2.replace('/', '.')); |
|
1300 |
} catch (Exception e) { |
|
1301 |
throw new RuntimeException(e.toString()); |
|
1302 |
} |
|
1303 |
if (c.isAssignableFrom(d)) { |
|
1304 |
return type1; |
|
1305 |
} |
|
1306 |
if (d.isAssignableFrom(c)) { |
|
1307 |
return type2; |
|
1308 |
} |
|
1309 |
if (c.isInterface() || d.isInterface()) { |
|
1310 |
return "java/lang/Object"; |
|
1311 |
} else { |
|
1312 |
do { |
|
1313 |
c = c.getSuperclass(); |
|
1314 |
} while (!c.isAssignableFrom(d)); |
|
1315 |
return c.getName().replace('.', '/'); |
|
1316 |
} |
|
1317 |
} |
|
1318 |
||
1319 |
/** |
|
1320 |
* Returns the constant pool's hash table item which is equal to the given |
|
1321 |
* item. |
|
1322 |
* |
|
1323 |
* @param key a constant pool item. |
|
1324 |
* @return the constant pool's hash table item which is equal to the given |
|
1325 |
* item, or <tt>null</tt> if there is no such item. |
|
1326 |
*/ |
|
1327 |
private Item get(final Item key) { |
|
1328 |
Item i = items[key.hashCode % items.length]; |
|
1329 |
while (i != null && !key.isEqualTo(i)) { |
|
1330 |
i = i.next; |
|
1331 |
} |
|
1332 |
return i; |
|
1333 |
} |
|
1334 |
||
1335 |
/** |
|
1336 |
* Puts the given item in the constant pool's hash table. The hash table |
|
1337 |
* <i>must</i> not already contains this item. |
|
1338 |
* |
|
1339 |
* @param i the item to be added to the constant pool's hash table. |
|
1340 |
*/ |
|
1341 |
private void put(final Item i) { |
|
1342 |
if (index > threshold) { |
|
1343 |
int ll = items.length; |
|
1344 |
int nl = ll * 2 + 1; |
|
1345 |
Item[] newItems = new Item[nl]; |
|
1346 |
for (int l = ll - 1; l >= 0; --l) { |
|
1347 |
Item j = items[l]; |
|
1348 |
while (j != null) { |
|
1349 |
int index = j.hashCode % newItems.length; |
|
1350 |
Item k = j.next; |
|
1351 |
j.next = newItems[index]; |
|
1352 |
newItems[index] = j; |
|
1353 |
j = k; |
|
1354 |
} |
|
1355 |
} |
|
1356 |
items = newItems; |
|
1357 |
threshold = (int) (nl * 0.75); |
|
1358 |
} |
|
1359 |
int index = i.hashCode % items.length; |
|
1360 |
i.next = items[index]; |
|
1361 |
items[index] = i; |
|
1362 |
} |
|
1363 |
||
1364 |
/** |
|
1365 |
* Puts one byte and two shorts into the constant pool. |
|
1366 |
* |
|
1367 |
* @param b a byte. |
|
1368 |
* @param s1 a short. |
|
1369 |
* @param s2 another short. |
|
1370 |
*/ |
|
1371 |
private void put122(final int b, final int s1, final int s2) { |
|
1372 |
pool.put12(b, s1).putShort(s2); |
|
1373 |
} |
|
1374 |
} |