/Users/lyon/j4p/src/javassist/CtClassType.java
|
1 /*
2 * Javassist, a Java-bytecode translator toolkit.
3 * Copyright (C) 1999-2003 Shigeru Chiba. All Rights Reserved.
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. Alternatively, the contents of this file may be used under
8 * the terms of the GNU Lesser General Public License Version 2.1 or later.
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 */
15
16 package javassist;
17
18 import javassist.bytecode.*;
19 import javassist.compiler.CompileError;
20 import javassist.compiler.Javac;
21 import javassist.expr.ExprEditor;
22
23 import java.io.*;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.Hashtable;
27 import java.util.List;
28
29 /**
30 * Class types.
31 */
32 class CtClassType extends CtClass {
33 protected ClassPool classPool;
34 protected boolean wasChanged;
35 protected boolean wasFrozen;
36 protected ClassFile classfile;
37
38 private CtField fieldsCache;
39 private CtConstructor constructorsCache;
40 private CtConstructor classInitializerCache;
41 private CtMethod methodsCache;
42
43 private FieldInitLink fieldInitializers;
44 private Hashtable hiddenMethods; // must be synchronous
45 private int uniqueNumberSeed;
46
47 CtClassType(String name, ClassPool cp) {
48 super(name);
49 classPool = cp;
50 wasChanged = wasFrozen = false;
51 classfile = null;
52 fieldInitializers = null;
53 hiddenMethods = null;
54 uniqueNumberSeed = 0;
55 eraseCache();
56 }
57
58 CtClassType(InputStream ins, ClassPool cp) throws IOException {
59 this((String) null, cp);
60 classfile = new ClassFile(new DataInputStream(ins));
61 qualifiedName = classfile.getName();
62 }
63
64 protected void eraseCache() {
65 fieldsCache = null;
66 constructorsCache = null;
67 classInitializerCache = null;
68 methodsCache = null;
69 }
70
71 public ClassFile getClassFile2() {
72 if (classfile != null)
73 return classfile;
74
75 try {
76 byte[] b = classPool.readSource(getName());
77 DataInputStream dis
78 = new DataInputStream(new ByteArrayInputStream(b));
79 return (classfile = new ClassFile(dis));
80 } catch (NotFoundException e) {
81 throw new RuntimeException(e.toString());
82 } catch (IOException e) {
83 throw new RuntimeException(e.toString());
84 } catch (CannotCompileException e) {
85 throw new RuntimeException(e.toString());
86 }
87 }
88
89 public ClassPool getClassPool() {
90 return classPool;
91 }
92
93 public boolean isModified() {
94 return wasChanged;
95 }
96
97 public boolean isFrozen() {
98 return wasFrozen;
99 }
100
101 void freeze() {
102 wasFrozen = true;
103 }
104
105 void checkModify() throws RuntimeException {
106 super.checkModify();
107 wasChanged = true;
108 }
109
110 public void defrost() {
111 wasFrozen = false;
112 }
113
114 public boolean subtypeOf(CtClass clazz) throws NotFoundException {
115 int i;
116 String cname = clazz.getName();
117 if (this == clazz || getName().equals(cname))
118 return true;
119
120 ClassFile file = getClassFile2();
121 String supername = file.getSuperclass();
122 if (supername != null && supername.equals(cname))
123 return true;
124
125 String[] ifs = file.getInterfaces();
126 int num = ifs.length;
127 for (i = 0; i < num; ++i)
128 if (ifs[i].equals(cname))
129 return true;
130
131 if (supername != null && classPool.get(supername).subtypeOf(clazz))
132 return true;
133
134 for (i = 0; i < num; ++i)
135 if (classPool.get(ifs[i]).subtypeOf(clazz))
136 return true;
137
138 return false;
139 }
140
141 public void setName(String name) throws RuntimeException {
142 String oldname = getName();
143 if (name.equals(oldname))
144 return;
145
146 classPool.checkNotFrozen(name,
147 "the class with the new name is frozen");
148 ClassFile cf = getClassFile2();
149 super.setName(name);
150 cf.setName(name);
151 eraseCache();
152 classPool.classNameChanged(oldname, this);
153 }
154
155 public void replaceClassName(ClassMap classnames)
156 throws RuntimeException {
157 String oldClassName = getName();
158 String newClassName
159 = (String) classnames.get(Descriptor.toJvmName(oldClassName));
160 if (newClassName != null) {
161 newClassName = Descriptor.toJavaName(newClassName);
162 classPool.checkNotFrozen(newClassName,
163 "the class " + newClassName + " is frozen");
164 }
165
166 super.replaceClassName(classnames);
167 ClassFile cf = getClassFile2();
168 cf.renameClass(classnames);
169 eraseCache();
170
171 if (newClassName != null) {
172 super.setName(newClassName);
173 classPool.classNameChanged(oldClassName, this);
174 }
175 }
176
177 public void replaceClassName(String oldname, String newname)
178 throws RuntimeException {
179 String thisname = getName();
180 if (thisname.equals(oldname))
181 setName(newname);
182 else {
183 super.replaceClassName(oldname, newname);
184 getClassFile2().renameClass(oldname, newname);
185 eraseCache();
186 }
187 }
188
189 public boolean isInterface() {
190 return Modifier.isInterface(getModifiers());
191 }
192
193 public int getModifiers() {
194 int acc = getClassFile2().getAccessFlags();
195 acc = AccessFlag.clear(acc, AccessFlag.SUPER);
196 return AccessFlag.toModifier(acc);
197 }
198
199 public void setModifiers(int mod) {
200 checkModify();
201 int acc = AccessFlag.of(mod) | AccessFlag.SUPER;
202 getClassFile2().setAccessFlags(acc);
203 }
204
205 public boolean subclassOf(CtClass superclass) {
206 if (superclass == null)
207 return false;
208
209 String superName = superclass.getName();
210 CtClass curr = this;
211 try {
212 while (curr != null) {
213 if (curr.getName().equals(superName))
214 return true;
215
216 curr = curr.getSuperclass();
217 }
218 } catch (Exception ignored) {
219 }
220 return false;
221 }
222
223 public CtClass getSuperclass() throws NotFoundException {
224 String supername = getClassFile2().getSuperclass();
225 if (supername == null)
226 return null;
227 else
228 return classPool.get(supername);
229 }
230
231 public void setSuperclass(CtClass clazz) throws CannotCompileException {
232 checkModify();
233 getClassFile2().setSuperclass(clazz.getName());
234 }
235
236 public CtClass[] getInterfaces() throws NotFoundException {
237 String[] ifs = getClassFile2().getInterfaces();
238 int num = ifs.length;
239 CtClass[] ifc = new CtClass[num];
240 for (int i = 0; i < num; ++i)
241 ifc[i] = classPool.get(ifs[i]);
242
243 return ifc;
244 }
245
246 public void setInterfaces(CtClass[] list) {
247 checkModify();
248 String[] ifs;
249 if (list == null)
250 ifs = new String[0];
251 else {
252 int num = list.length;
253 ifs = new String[num];
254 for (int i = 0; i < num; ++i)
255 ifs[i] = list[i].getName();
256 }
257
258 getClassFile2().setInterfaces(ifs);
259 }
260
261 public void addInterface(CtClass anInterface) {
262 checkModify();
263 if (anInterface != null)
264 getClassFile2().addInterface(anInterface.getName());
265 }
266
267 public CtField[] getFields() {
268 ArrayList alist = new ArrayList();
269 getFields(alist, this);
270 return (CtField[]) alist.toArray(new CtField[alist.size()]);
271 }
272
273 private static void getFields(ArrayList alist, CtClass cc) {
274 int i, num;
275 if (cc == null)
276 return;
277
278 try {
279 getFields(alist, cc.getSuperclass());
280 } catch (NotFoundException e) {
281 }
282
283 try {
284 CtClass[] ifs = cc.getInterfaces();
285 num = ifs.length;
286 for (i = 0; i < num; ++i)
287 getFields(alist, ifs[i]);
288 } catch (NotFoundException e) {
289 }
290
291 CtField cf = ((CtClassType) cc).getFieldsCache();
292 while (cf != null) {
293 if (Modifier.isPublic(cf.getModifiers()))
294 alist.add(cf);
295
296 cf = cf.next;
297 }
298 }
299
300 public CtField getField(String name) throws NotFoundException {
301 try {
302 return getDeclaredField(name);
303 } catch (NotFoundException e) {
304 }
305
306 try {
307 CtClass[] ifs = getInterfaces();
308 int num = ifs.length;
309 for (int i = 0; i < num; ++i)
310 try {
311 return ifs[i].getField(name);
312 } catch (NotFoundException e) {
313 }
314 } catch (NotFoundException e) {
315 }
316
317 try {
318 CtClass s = getSuperclass();
319 if (s != null)
320 return s.getField(name);
321 } catch (NotFoundException e) {
322 }
323
324 throw new NotFoundException(name);
325 }
326
327 public CtField[] getDeclaredFields() {
328 CtField cf = getFieldsCache();
329 int num = CtField.count(cf);
330 CtField[] cfs = new CtField[num];
331 int i = 0;
332 while (cf != null) {
333 cfs[i++] = cf;
334 cf = cf.next;
335 }
336
337 return cfs;
338 }
339
340 protected CtField getFieldsCache() {
341 if (fieldsCache == null) {
342 List list = getClassFile2().getFields();
343 int n = list.size();
344 for (int i = 0; i < n; ++i) {
345 FieldInfo finfo = (FieldInfo) list.get(i);
346 fieldsCache = CtField.append(fieldsCache,
347 new CtField(finfo, this));
348 }
349 }
350
351 return fieldsCache;
352 }
353
354 public CtField getDeclaredField(String name) throws NotFoundException {
355 CtField cf = getFieldsCache();
356 while (cf != null) {
357 if (cf.getName().equals(name))
358 return cf;
359
360 cf = cf.next;
361 }
362
363 throw new NotFoundException(name);
364 }
365
366 public CtBehavior[] getDeclaredBehaviors() {
367 CtConstructor cc = getConstructorsCache();
368 CtMethod cm = getMethodsCache();
369 int num = CtMethod.count(cm) + CtConstructor.count(cc);
370 CtBehavior[] cb = new CtBehavior[num];
371 int i = 0;
372 while (cc != null) {
373 cb[i++] = cc;
374 cc = cc.next;
375 }
376
377 while (cm != null) {
378 cb[i++] = cm;
379 cm = cm.next;
380 }
381
382 return cb;
383 }
384
385 public CtConstructor[] getConstructors() {
386 CtConstructor[] cons = getDeclaredConstructors();
387 if (cons.length == 0)
388 return cons;
389
390 int n = 0;
391 int i = cons.length;
392 while (--i >= 0)
393 if (Modifier.isPublic(cons[i].getModifiers()))
394 ++n;
395
396 CtConstructor[] result = new CtConstructor[n];
397 n = 0;
398 i = cons.length;
399 while (--i >= 0) {
400 CtConstructor c = cons[i];
401 if (Modifier.isPublic(c.getModifiers()))
402 result[n++] = c;
403 }
404
405 return result;
406 }
407
408 public CtConstructor getConstructor(String desc)
409 throws NotFoundException {
410 CtConstructor cc = getConstructorsCache();
411 while (cc != null) {
412 if (cc.getMethodInfo2().getDescriptor().equals(desc))
413 return cc;
414
415 cc = cc.next;
416 }
417
418 return super.getConstructor(desc);
419 }
420
421 public CtConstructor[] getDeclaredConstructors() {
422 CtConstructor cc = getConstructorsCache();
423 int num = CtConstructor.count(cc);
424 CtConstructor[] ccs = new CtConstructor[num];
425 int i = 0;
426 while (cc != null) {
427 ccs[i++] = cc;
428 cc = cc.next;
429 }
430
431 return ccs;
432 }
433
434 protected CtConstructor getConstructorsCache() {
435 if (constructorsCache == null) {
436 List list = getClassFile2().getMethods();
437 int n = list.size();
438 for (int i = 0; i < n; ++i) {
439 MethodInfo minfo = (MethodInfo) list.get(i);
440 if (minfo.isConstructor())
441 constructorsCache
442 = CtConstructor.append(constructorsCache,
443 new CtConstructor(minfo, this));
444 }
445 }
446
447 return constructorsCache;
448 }
449
450 public CtConstructor getClassInitializer() {
451 if (classInitializerCache == null) {
452 MethodInfo minfo = getClassFile2().getStaticInitializer();
453 if (minfo != null)
454 classInitializerCache = new CtConstructor(minfo, this);
455 }
456
457 return classInitializerCache;
458 }
459
460 public CtMethod[] getMethods() {
461 HashMap h = new HashMap();
462 getMethods0(h, this);
463 return (CtMethod[]) h.values().toArray(new CtMethod[0]);
464 }
465
466 private static void getMethods0(HashMap h, CtClass cc) {
467 try {
468 CtClass[] ifs = cc.getInterfaces();
469 int size = ifs.length;
470 for (int i = 0; i < size; ++i)
471 getMethods0(h, ifs[i]);
472 } catch (NotFoundException e) {
473 }
474
475 try {
476 CtClass s = cc.getSuperclass();
477 if (s != null)
478 getMethods0(h, s);
479 } catch (NotFoundException e) {
480 }
481
482 if (cc instanceof CtClassType) {
483 CtMethod cm = ((CtClassType) cc).getMethodsCache();
484 while (cm != null) {
485 if (Modifier.isPublic(cm.getModifiers()))
486 h.put(cm, cm);
487
488 cm = cm.next;
489 }
490 }
491 }
492
493 public CtMethod getMethod(String name, String desc)
494 throws NotFoundException {
495 CtMethod m = getMethod0(this, name, desc);
496 if (m != null)
497 return m;
498 else
499 throw new NotFoundException(name + "(..) is not found in "
500 + getName());
501 }
502
503 private static CtMethod getMethod0(CtClass cc,
504 String name, String desc) {
505 if (cc instanceof CtClassType) {
506 CtMethod cm = ((CtClassType) cc).getMethodsCache();
507 while (cm != null) {
508 if (cm.getName().equals(name)
509 && cm.getMethodInfo2().getDescriptor().equals(desc))
510 return cm;
511
512 cm = cm.next;
513 }
514 }
515
516 try {
517 CtClass s = cc.getSuperclass();
518 if (s != null) {
519 CtMethod m = getMethod0(s, name, desc);
520 if (m != null)
521 return m;
522 }
523 } catch (NotFoundException e) {
524 }
525
526 try {
527 CtClass[] ifs = cc.getInterfaces();
528 int size = ifs.length;
529 for (int i = 0; i < size; ++i) {
530 CtMethod m = getMethod0(ifs[i], name, desc);
531 if (m != null)
532 return m;
533 }
534 } catch (NotFoundException e) {
535 }
536 return null;
537 }
538
539 public CtMethod[] getDeclaredMethods() {
540 CtMethod cm = getMethodsCache();
541 int num = CtMethod.count(cm);
542 CtMethod[] cms = new CtMethod[num];
543 int i = 0;
544 while (cm != null) {
545 cms[i++] = cm;
546 cm = cm.next;
547 }
548
549 return cms;
550 }
551
552 public CtMethod getDeclaredMethod(String name) throws NotFoundException {
553 CtMethod m = getMethodsCache();
554 while (m != null) {
555 if (m.getName().equals(name))
556 return m;
557
558 m = m.next;
559 }
560
561 throw new NotFoundException(name + "(..) is not found in "
562 + getName());
563 }
564
565 public CtMethod getDeclaredMethod(String name, CtClass[] params)
566 throws NotFoundException {
567 String desc = Descriptor.ofParameters(params);
568 CtMethod m = getMethodsCache();
569 while (m != null) {
570 if (m.getName().equals(name)
571 && m.getMethodInfo2().getDescriptor().startsWith(desc))
572 return m;
573
574 m = m.next;
575 }
576
577 throw new NotFoundException(name + "(..) is not found in "
578 + getName());
579 }
580
581 protected CtMethod getMethodsCache() {
582 if (methodsCache == null) {
583 List list = getClassFile2().getMethods();
584 int n = list.size();
585 for (int i = 0; i < n; ++i) {
586 MethodInfo minfo = (MethodInfo) list.get(i);
587 if (minfo.isMethod())
588 methodsCache = CtMethod.append(methodsCache,
589 new CtMethod(minfo, this));
590 }
591 }
592
593 return methodsCache;
594 }
595
596 public void addField(CtField f, String init)
597 throws CannotCompileException {
598 addField(f, CtField.Initializer.byExpr(init));
599 }
600
601 public void addField(CtField f, CtField.Initializer init)
602 throws CannotCompileException {
603 checkModify();
604 if (f.getDeclaringClass() != this)
605 throw new CannotCompileException("cannot add");
606
607 if (init == null)
608 init = f.getInit();
609
610 getFieldsCache();
611 fieldsCache = CtField.append(fieldsCache, f);
612 getClassFile2().addField(f.getFieldInfo2());
613
614 if (init != null) {
615 FieldInitLink fil = new FieldInitLink(f, init);
616 FieldInitLink link = fieldInitializers;
617 if (link == null)
618 fieldInitializers = fil;
619 else {
620 while (link.next != null)
621 link = link.next;
622
623 link.next = fil;
624 }
625 }
626 }
627
628 public CtConstructor makeClassInitializer()
629 throws CannotCompileException {
630 CtConstructor clinit = getClassInitializer();
631 if (clinit != null)
632 return clinit;
633
634 checkModify();
635 ClassFile cf = getClassFile2();
636 Bytecode code = new Bytecode(cf.getConstPool(), 0, 0);
637 modifyClassConstructor(cf, code, 0, 0);
638 return getClassInitializer();
639 }
640
641 public void addConstructor(CtConstructor c)
642 throws CannotCompileException {
643 checkModify();
644 if (c.getDeclaringClass() != this)
645 throw new CannotCompileException("cannot add");
646
647 getConstructorsCache();
648 constructorsCache = CtConstructor.append(constructorsCache, c);
649 getClassFile2().addMethod(c.getMethodInfo2());
650 }
651
652 public void addMethod(CtMethod m) throws CannotCompileException {
653 checkModify();
654 if (m.getDeclaringClass() != this)
655 throw new CannotCompileException("cannot add");
656
657 getMethodsCache();
658 methodsCache = CtMethod.append(methodsCache, m);
659 getClassFile2().addMethod(m.getMethodInfo2());
660 if ((m.getModifiers() & Modifier.ABSTRACT) != 0)
661 setModifiers(getModifiers() | Modifier.ABSTRACT);
662 }
663
664 public byte[] getAttribute(String name) {
665 AttributeInfo ai = getClassFile2().getAttribute(name);
666 if (ai == null)
667 return null;
668 else
669 return ai.get();
670 }
671
672 public void setAttribute(String name, byte[] data) {
673 checkModify();
674 ClassFile cf = getClassFile2();
675 cf.addAttribute(new AttributeInfo(cf.getConstPool(), name, data));
676 }
677
678 public void instrument(CodeConverter converter)
679 throws CannotCompileException {
680 checkModify();
681 ClassFile cf = getClassFile2();
682 ConstPool cp = cf.getConstPool();
683 List list = cf.getMethods();
684 int n = list.size();
685 for (int i = 0; i < n; ++i) {
686 MethodInfo minfo = (MethodInfo) list.get(i);
687 converter.doit(this, minfo, cp);
688 }
689 }
690
691 public void instrument(ExprEditor editor)
692 throws CannotCompileException {
693 checkModify();
694 ClassFile cf = getClassFile2();
695 List list = cf.getMethods();
696 int n = list.size();
697 for (int i = 0; i < n; ++i) {
698 MethodInfo minfo = (MethodInfo) list.get(i);
699 editor.doit(this, minfo);
700 }
701 }
702
703 void toBytecode(DataOutputStream out)
704 throws CannotCompileException, IOException {
705 ClassFile cf = getClassFile2();
706 try {
707 modifyClassConstructor(cf);
708 modifyConstructors(cf);
709 } catch (NotFoundException e) {
710 throw new CannotCompileException(e);
711 }
712
713 wasFrozen = true;
714 try {
715 cf.write(out);
716 out.flush();
717 } catch (IOException e) {
718 throw new CannotCompileException(e);
719 }
720 }
721
722 protected void modifyClassConstructor(ClassFile cf)
723 throws CannotCompileException, NotFoundException {
724 Bytecode code = new Bytecode(cf.getConstPool(), 0, 0);
725 Javac jv = new Javac(code, this);
726 int stacksize = 0;
727 boolean doInit = false;
728 for (FieldInitLink fi = fieldInitializers; fi != null; fi = fi.next) {
729 CtField f = fi.field;
730 if (Modifier.isStatic(f.getModifiers())) {
731 doInit = true;
732 int s = fi.init.compileIfStatic(f.getType(), f.getName(),
733 code, jv);
734 if (stacksize < s)
735 stacksize = s;
736 }
737 }
738
739 if (doInit) // need an initializer for static fileds.
740 modifyClassConstructor(cf, code, stacksize, 0);
741 }
742
743 private void modifyClassConstructor(ClassFile cf, Bytecode code,
744 int stacksize, int localsize)
745 throws CannotCompileException {
746 MethodInfo m = cf.getStaticInitializer();
747 if (m == null) {
748 code.add(Bytecode.RETURN);
749 code.setMaxStack(stacksize);
750 code.setMaxLocals(localsize);
751 m = new MethodInfo(cf.getConstPool(), "<clinit>", "()V");
752 m.setAccessFlags(AccessFlag.STATIC);
753 m.setCodeAttribute(code.toCodeAttribute());
754 cf.addMethod(m);
755 } else {
756 CodeAttribute codeAttr = m.getCodeAttribute();
757 if (codeAttr == null)
758 throw new CannotCompileException("empty <clinit>");
759
760 try {
761 CodeIterator it = codeAttr.iterator();
762 int pos = it.insertEx(code.get());
763 it.insert(code.getExceptionTable(), pos);
764 int maxstack = codeAttr.getMaxStack();
765 if (maxstack < stacksize)
766 codeAttr.setMaxStack(stacksize);
767
768 int maxlocals = codeAttr.getMaxLocals();
769 if (maxlocals < localsize)
770 codeAttr.setMaxLocals(localsize);
771 } catch (BadBytecode e) {
772 throw new CannotCompileException(e);
773 }
774 }
775 }
776
777 protected void modifyConstructors(ClassFile cf)
778 throws CannotCompileException, NotFoundException {
779 if (fieldInitializers == null)
780 return;
781
782 ConstPool cp = cf.getConstPool();
783 List list = cf.getMethods();
784 int n = list.size();
785 for (int i = 0; i < n; ++i) {
786 MethodInfo minfo = (MethodInfo) list.get(i);
787 if (minfo.isConstructor()) {
788 CodeAttribute codeAttr = minfo.getCodeAttribute();
789 if (codeAttr != null)
790 try {
791 Bytecode init = new Bytecode(cp, 0,
792 codeAttr.getMaxLocals());
793 CtClass[] params
794 = Descriptor.getParameterTypes(
795 minfo.getDescriptor(),
796 classPool);
797 int stacksize = makeFieldInitializer(init, params);
798 insertAuxInitializer(codeAttr, init, stacksize);
799 } catch (BadBytecode e) {
800 throw new CannotCompileException(e);
801 }
802 }
803 }
804 }
805
806 private static void insertAuxInitializer(CodeAttribute codeAttr,
807 Bytecode initializer,
808 int stacksize)
809 throws BadBytecode {
810 CodeIterator it = codeAttr.iterator();
811 int index = it.skipSuperConstructor();
812 if (index < 0) {
813 index = it.skipThisConstructor();
814 if (index >= 0)
815 return; // this() is called.
816
817 // Neither this() or super() is called.
818 }
819
820 int pos = it.insertEx(initializer.get());
821 it.insert(initializer.getExceptionTable(), pos);
822 int maxstack = codeAttr.getMaxStack();
823 if (maxstack < stacksize)
824 codeAttr.setMaxStack(stacksize);
825 }
826
827 private int makeFieldInitializer(Bytecode code, CtClass[] parameters)
828 throws CannotCompileException, NotFoundException {
829 int stacksize = 0;
830 Javac jv = new Javac(code, this);
831 try {
832 jv.recordParams(parameters, false);
833 } catch (CompileError e) {
834 throw new CannotCompileException(e);
835 }
836
837 for (FieldInitLink fi = fieldInitializers; fi != null; fi = fi.next) {
838 CtField f = fi.field;
839 if (!Modifier.isStatic(f.getModifiers())) {
840 int s = fi.init.compile(f.getType(), f.getName(), code,
841 parameters, jv);
842 if (stacksize < s)
843 stacksize = s;
844 }
845 }
846
847 return stacksize;
848 }
849
850 // Methods used by CtNewWrappedMethod
851
852 Hashtable getHiddenMethods() {
853 if (hiddenMethods == null)
854 hiddenMethods = new Hashtable();
855
856 return hiddenMethods;
857 }
858
859 int getUniqueNumber() {
860 return uniqueNumberSeed++;
861 }
862 }
863
864 class FieldInitLink {
865 FieldInitLink next;
866 CtField field;
867 CtField.Initializer init;
868
869 FieldInitLink(CtField f, CtField.Initializer i) {
870 next = null;
871 field = f;
872 init = i;
873 }
874 }
875