Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: Bootstrap/BootstrapRootSet.java


1   // BootstrapRootSet.java, created Wed Jun 26 12:27:23 2002 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package Bootstrap;
5   
6   import java.util.HashSet;
7   import java.util.Iterator;
8   import java.util.LinkedHashSet;
9   import java.util.LinkedList;
10  import java.util.List;
11  import java.util.Set;
12  
13  import Clazz.jq_Array;
14  import Clazz.jq_Class;
15  import Clazz.jq_ClassInitializer;
16  import Clazz.jq_Field;
17  import Clazz.jq_FieldVisitor;
18  import Clazz.jq_Initializer;
19  import Clazz.jq_InstanceField;
20  import Clazz.jq_InstanceMethod;
21  import Clazz.jq_Member;
22  import Clazz.jq_Method;
23  import Clazz.jq_MethodVisitor;
24  import Clazz.jq_Primitive;
25  import Clazz.jq_Reference;
26  import Clazz.jq_StaticField;
27  import Clazz.jq_StaticMethod;
28  import Clazz.jq_Type;
29  import Clazz.jq_TypeVisitor;
30  import Memory.CodeAddress;
31  import Memory.HeapAddress;
32  import Memory.StackAddress;
33  import Run_Time.ExceptionDeliverer;
34  import Run_Time.Reflection;
35  import Run_Time.SystemInterface;
36  import Run_Time.Unsafe;
37  import Util.Assert;
38  import Util.Collections.IdentityHashCodeWrapper;
39  
40  /**
41   * BootstrapRootSet
42   *
43   * @author  John Whaley <jwhaley@alum.mit.edu>
44   * @version $Id: BootstrapRootSet.java,v 1.26 2003/05/12 10:04:52 joewhaley Exp $
45   */
46  public class BootstrapRootSet {
47  
48      public static /*final*/ boolean TRACE = false;
49      public static final java.io.PrintStream out = System.out;
50      
51      protected final Set/*jq_Type*/ instantiatedTypes;
52      protected final Set/*jq_Type*/ necessaryTypes;
53      protected final Set/*jq_Field*/ necessaryFields;
54      protected final Set/*jq_Method*/ necessaryMethods;
55      
56      protected final LinkedHashSet/*Object*/ visitedObjects;
57      
58      protected List/*jq_TypeVisitor*/ instantiatedTypesListeners;
59      protected List/*jq_TypeVisitor*/ necessaryTypesListeners;
60      protected List/*jq_FieldVisitor*/ necessaryFieldsListeners;
61      protected List/*jq_MethodVisitor*/ necessaryMethodsListeners;
62      
63      public boolean AddAllFields;
64      
65      /** Creates new BootstrapRootSet */
66      public BootstrapRootSet(boolean addall) {
67          this.instantiatedTypes = new HashSet();
68          this.necessaryTypes = new HashSet();
69          this.necessaryFields = new HashSet();
70          this.necessaryMethods = new HashSet();
71          this.visitedObjects = new LinkedHashSet();
72          this.AddAllFields = addall;
73      }
74      
75      public Set/*jq_Type*/ getInstantiatedTypes() { return instantiatedTypes; }
76      public Set/*jq_Type*/ getNecessaryTypes() { return necessaryTypes; }
77      public Set/*jq_Field*/ getNecessaryFields() { return necessaryFields; }
78      public Set/*jq_Method*/ getNecessaryMethods() { return necessaryMethods; }
79      
80      public void registerInstantiatedTypeListener(jq_TypeVisitor tv) {
81          if (instantiatedTypesListeners == null)
82              instantiatedTypesListeners = new LinkedList();
83          instantiatedTypesListeners.add(tv);
84      }
85      public void unregisterInstantiatedTypeListener(jq_TypeVisitor tv) {
86          instantiatedTypesListeners.remove(tv);
87      }
88      public void registerNecessaryTypeListener(jq_TypeVisitor tv) {
89          if (necessaryTypesListeners == null)
90              necessaryTypesListeners = new LinkedList();
91          necessaryTypesListeners.add(tv);
92      }
93      public void unregisterNecessaryTypeListener(jq_TypeVisitor tv) {
94          necessaryTypesListeners.remove(tv);
95      }
96      public void registerNecessaryFieldListener(jq_FieldVisitor tv) {
97          if (necessaryFieldsListeners == null)
98              necessaryFieldsListeners = new LinkedList();
99          necessaryFieldsListeners.add(tv);
100     }
101     public void unregisterNecessaryFieldListener(jq_FieldVisitor tv) {
102         necessaryFieldsListeners.remove(tv);
103     }
104     public void registerNecessaryMethodListener(jq_MethodVisitor tv) {
105         if (necessaryMethodsListeners == null)
106             necessaryMethodsListeners = new LinkedList();
107         necessaryMethodsListeners.add(tv);
108     }
109     public void unregisterNecessaryMethodListener(jq_MethodVisitor tv) {
110         necessaryMethodsListeners.remove(tv);
111     }
112     
113     public boolean addInstantiatedType(jq_Type t) {
114         Assert._assert(t != null);
115         addNecessaryType(t);
116         boolean b = instantiatedTypes.add(t);
117         if (b) {
118             if (TRACE) out.println("New instantiated type: "+t);
119             if (instantiatedTypesListeners != null) {
120                 for (Iterator i=instantiatedTypesListeners.iterator(); i.hasNext(); ) {
121                     jq_TypeVisitor tv = (jq_TypeVisitor)i.next();
122                     t.accept(tv);
123                 }
124             }
125         }
126         return b;
127     }
128     
129     public jq_Type addNecessaryType(String desc) {
130         String className = desc.substring(1, desc.length()-1).replace('/', '.');
131         try {
132             // attempt to load class in host VM first.
133             Class.forName(className);
134             jq_Type t = null;
135             try {
136                 t = PrimordialClassLoader.loader.getOrCreateBSType(desc);
137                 t.load();
138                 addNecessaryType(t);
139                 return t;
140             } catch (NoClassDefFoundError x) {
141                 System.out.println("Note: Cannot load class "+t+" present in host Jvm");
142                 PrimordialClassLoader.unloadType(PrimordialClassLoader.loader, t);
143             }
144         } catch (ClassNotFoundException x) { }
145         return null;
146     }
147         
148     public boolean addNecessaryType(jq_Type t) {
149         if (t == null) return false;
150         t.prepare();
151         boolean b = necessaryTypes.add(t);
152         if (b) {
153             if (TRACE) out.println("New necessary type: "+t);
154             if (necessaryTypesListeners != null) {
155                 for (Iterator i=necessaryTypesListeners.iterator(); i.hasNext(); ) {
156                     jq_TypeVisitor tv = (jq_TypeVisitor)i.next();
157                     t.accept(tv);
158                 }
159             }
160             if (t instanceof jq_Class) {
161                 jq_Class klass = (jq_Class)t;
162                 if (AddAllFields) {
163                     jq_StaticField[] sfs = klass.getDeclaredStaticFields();
164                     for (int i=0; i<sfs.length; ++i) {
165                         addNecessaryField(sfs[i]);
166                     }
167                 }
168                 // add superclass as necessary, as well.
169                 addNecessaryType(klass.getSuperclass());
170             }
171         }
172         return b;
173     }
174     
175     public jq_StaticField addNecessaryStaticField(jq_Class c, String name, String desc) {
176         if (c == null) return null;
177         jq_StaticField f = c.getOrCreateStaticField(name, desc);
178         addNecessaryField(f);
179         return f;
180     }
181     
182     public jq_InstanceField addNecessaryInstanceField(jq_Class c, String name, String desc) {
183         if (c == null) return null;
184         jq_InstanceField f = c.getOrCreateInstanceField(name, desc);
185         addNecessaryField(f);
186         return f;
187     }
188         
189     public boolean addNecessaryField(jq_Field t) {
190         addNecessaryType(t.getDeclaringClass());
191         boolean b = necessaryFields.add(t);
192         if (b) {
193             if (TRACE) out.println("New necessary field: "+t);
194             if (necessaryFieldsListeners != null) {
195                 for (Iterator i=necessaryFieldsListeners.iterator(); i.hasNext(); ) {
196                     jq_FieldVisitor tv = (jq_FieldVisitor)i.next();
197                     t.accept(tv);
198                 }
199             }
200         }
201         return b;
202     }
203     
204     public jq_StaticMethod addNecessaryStaticMethod(jq_Class c, String name, String desc) {
205         if (c == null) return null;
206         jq_StaticMethod f = c.getOrCreateStaticMethod(name, desc);
207         addNecessaryMethod(f);
208         return f;
209     }
210     
211     public jq_InstanceMethod addNecessaryInstanceMethod(jq_Class c, String name, String desc) {
212         if (c == null) return null;
213         jq_InstanceMethod f = c.getOrCreateInstanceMethod(name, desc);
214         addNecessaryMethod(f);
215         return f;
216     }
217         
218     public boolean addNecessaryMethod(jq_Method t) {
219         addNecessaryType(t.getDeclaringClass());
220         boolean b = necessaryMethods.add(t);
221         if (b) {
222             if (TRACE) out.println("New necessary method: "+t);
223             if (necessaryMethodsListeners != null) {
224                 for (Iterator i=necessaryMethodsListeners.iterator(); i.hasNext(); ) {
225                     jq_MethodVisitor tv = (jq_MethodVisitor)i.next();
226                     t.accept(tv);
227                 }
228             }
229         }
230         return b;
231     }
232     
233     public void addDefaultRoots() {
234         jq_Class c;
235         jq_StaticField s_f; jq_InstanceField i_f;
236         jq_StaticMethod s_m; jq_InstanceMethod i_m;
237         
238         // some internal vm data structures are necessary for correct execution
239         // under just about any circumstances.
240         addNecessaryType(jq_Class._class);
241         addNecessaryType(jq_Primitive._class);
242         addNecessaryType(jq_Array._class);
243         addNecessaryType(jq_InstanceField._class);
244         addNecessaryType(jq_StaticField._class);
245         addNecessaryType(jq_InstanceMethod._class);
246         addNecessaryType(jq_StaticMethod._class);
247         addNecessaryType(jq_Initializer._class);
248         addNecessaryType(jq_ClassInitializer._class);
249         addNecessaryType(CodeAddress._class);
250         addNecessaryType(HeapAddress._class);
251         addNecessaryType(StackAddress._class);
252         addNecessaryField(jq_Reference._vtable);
253         
254         // the bootstrap loader uses the static fields in the SystemInterface class.
255         SystemInterface._class.load();
256         jq_StaticField[] sfs = SystemInterface._class.getDeclaredStaticFields();
257         for (int i=0; i<sfs.length; ++i) {
258             addNecessaryField(sfs[i]);
259         }
260         // even if there are no calls to these Unsafe methods, we need their definitions
261         // to stick around so that we can check against them.
262         Unsafe._class.load();
263         jq_StaticMethod[] sms = Unsafe._class.getDeclaredStaticMethods();
264         for (int i=0; i<sms.length; ++i) {
265             if (sms[i] instanceof jq_ClassInitializer) continue;
266             addNecessaryMethod(sms[i]);
267         }
268         //addNecessaryField(Unsafe._remapper_object);
269 
270         // We need to be able to allocate objects and code.
271         addNecessaryType(Allocator.SimpleAllocator._class);
272         addNecessaryType(PrimordialClassLoader.loader.getOrCreateBSType("LAllocator/RuntimeCodeAllocator;"));
273         
274         // setIn0, setOut0, and setErr0 use these fields, but the trimmer doesn't detect the uses.
275         c = PrimordialClassLoader.getJavaLangSystem();
276         addNecessaryStaticField(c, "in", "Ljava/io/InputStream;");
277         addNecessaryStaticField(c, "out", "Ljava/io/PrintStream;");
278         addNecessaryStaticField(c, "err", "Ljava/io/PrintStream;");
279         
280         // private method initializeSystemClass is called reflectively
281         addNecessaryStaticMethod(c, "initializeSystemClass", "()V");
282         
283         // an instance of this class is created via reflection during VM initialization.
284         c = (jq_Class)Reflection.getJQType(sun.io.CharToByteConverter.getDefault().getClass());
285         addNecessaryInstanceMethod(c, "<init>", "()V");
286         
287         // an instance of this class is created via reflection during VM initialization.
288         c = (jq_Class)Reflection.getJQType(sun.io.ByteToCharConverter.getDefault().getClass());
289         addNecessaryInstanceMethod(c, "<init>", "()V");
290         
291         // the trap handler can be implicitly called from any bytecode than can trigger a hardware exception.
292         s_m = ExceptionDeliverer._trap_handler;
293         addNecessaryMethod(s_m);
294         
295         // we want the compiler to be able to run at run time, too.
296         i_m = jq_Method._compile;
297         addNecessaryMethod(i_m);
298         
299         // debugger is large, so compile it on demand.
300         if (false) {
301             s_m = ExceptionDeliverer._debug_trap_handler;
302             addNecessaryMethod(s_m);
303         }
304         
305         // entrypoint for new threads
306         addNecessaryMethod(Scheduler.jq_NativeThread._nativeThreadEntry);
307         // thread switch interrupt
308         addNecessaryMethod(Scheduler.jq_NativeThread._threadSwitch);
309         // ctrl-break handler
310         addNecessaryMethod(Scheduler.jq_NativeThread._ctrl_break_handler);
311         // entrypoint for interrupter thread
312         addNecessaryMethod(Scheduler.jq_InterrupterThread._run);
313         
314         // dunno why this doesn't show up
315         addNecessaryType(Assembler.x86.Heap2HeapReference._class);
316         
317         try {
318             // an instance of this class is created via reflection during VM initialization.
319             c = (jq_Class)Reflection.getJQType(sun.io.ByteToCharConverter.getConverter("ISO-8859-1").getClass());
320             addNecessaryInstanceMethod(c, "<init>", "()V");
321             // an instance of this class is created via reflection during VM initialization.
322             c = (jq_Class)Reflection.getJQType(sun.io.CharToByteConverter.getConverter("ISO-8859-1").getClass());
323             addNecessaryInstanceMethod(c, "<init>", "()V");
324         } catch (java.io.UnsupportedEncodingException x) { }
325 
326         // JDK1.4: an instance of this class is created via reflection during VM initialization.
327         c = (jq_Class) addNecessaryType("Lsun/nio/cs/ISO_8859_1;");
328         addNecessaryInstanceMethod(c, "<init>", "()V");
329         
330         addNecessaryType("Lsun/nio/cs/ISO_8859_1$Encoder;");
331         addNecessaryType("Lsun/nio/cs/ISO_8859_1$Decoder;");
332         addNecessaryType("Lsun/nio/cs/ISO_8859_1$1;");
333         
334         // for JDK1.4.2
335         addNecessaryType("Lsun/net/www/protocol/jar/Handler;");
336         addNecessaryType("Ljava/util/logging/LogManager$Cleaner;");
337         
338         // tracing in the compiler uses these
339         //c = jq._class; c.prepare();
340         //addToWorklist(jq._hex8);
341         //addToWorklist(jq._hex16);
342     }
343     
344     public boolean addObjectAndSubfields(Object o) {
345         return addObjectAndSubfields(o, visitedObjects);
346     }
347     private boolean addObjectAndSubfields(Object o, LinkedHashSet objs) {
348         if (o == null) return false;
349         IdentityHashCodeWrapper a = IdentityHashCodeWrapper.create(o);
350         if (visitedObjects.contains(a) || objs.contains(a))
351             return false;
352         objs.add(a);
353         Class objType = o.getClass();
354         jq_Reference jqType = (jq_Reference)Reflection.getJQType(objType);
355         if (TRACE) out.println("Adding object of type "+jqType+": "+o);
356         addInstantiatedType(jqType);
357         /*
358                 addClassInitializer((jq_Class)jqType);
359                 addSuperclassVirtualMethods((jq_Class)jqType);
360                 addClassInterfaceImplementations((jq_Class)jqType);
361          */
362         if (jqType.isArrayType()) {
363             jq_Type elemType = ((jq_Array)jqType).getElementType();
364             if (elemType.isAddressType()) {
365                 // no need to visit.
366             } else if (elemType.isReferenceType()) {
367                 int length = java.lang.reflect.Array.getLength(o);
368                 Object[] v = (Object[])o;
369                 if (TRACE) out.println("Visiting "+jqType+" of "+length+" elements");
370                 for (int k=0; k<length; ++k) {
371                     Object o2 = Reflection.arrayload_A(v, k);
372                     addObjectAndSubfields(o2, objs);
373                 }
374             }
375         } else {
376             Assert._assert(jqType.isClassType());
377             jq_Class clazz = (jq_Class)jqType;
378             jq_InstanceField[] fields = clazz.getInstanceFields();
379             for (int k=0; k<fields.length; ++k) {
380                 jq_InstanceField f = fields[k];
381                 if (!AddAllFields && !necessaryFields.contains(f))
382                     continue;
383                 jq_Type ftype = f.getType();
384                 if (ftype.isAddressType()) {
385                     // no need to visit.
386                 } else if (ftype.isReferenceType()) {
387                     if (TRACE) out.println("Visiting field "+f);
388                     Object o2 = Reflection.getfield_A(o, f);
389                     addObjectAndSubfields(o2, objs);
390                 }
391             }
392         }
393         return true;
394     }
395     
396     public void addNecessarySubfieldsOfVisitedObjects() {
397         if (AddAllFields) return;
398         LinkedHashSet objs = visitedObjects;
399         for (;;) {
400             LinkedHashSet objs2 = new LinkedHashSet();
401             boolean change = false;
402             for (Iterator i = objs.iterator(); i.hasNext(); ) {
403                 Object o = ((IdentityHashCodeWrapper)i.next()).getObject();
404                 Class objType = o.getClass();
405                 jq_Reference jqType = (jq_Reference)Reflection.getJQType(objType);
406                 if (jqType.isArrayType()) continue;
407                 Assert._assert(jqType.isClassType());
408                 jq_Class clazz = (jq_Class)jqType;
409                 jq_InstanceField[] fields = clazz.getInstanceFields();
410                 for (int k=0; k<fields.length; ++k) {
411                     jq_InstanceField f = fields[k];
412                     if (!necessaryFields.contains(f))
413                         continue;
414                     jq_Type ftype = f.getType();
415                     if (ftype.isAddressType()) {
416                         // no need to visit.
417                     } else if (ftype.isReferenceType()) {
418                         if (TRACE) out.println("Visiting field "+f+" of object of type "+clazz);
419                         Object o2 = Reflection.getfield_A(o, f);
420                         if (addObjectAndSubfields(o2, objs2))
421                             change = true;
422                     }
423                 }
424             }
425             if (!change) break;
426             if (TRACE) out.println("Objects added: "+objs2.size()+", iterating over those objects.");
427             visitedObjects.addAll(objs2);
428             objs = objs2;
429         }
430     }
431     
432     public void addAllInterfaceMethodImplementations(jq_InstanceMethod i_m) {
433         addNecessaryMethod(i_m);
434         jq_Class interf = i_m.getDeclaringClass();
435         Assert._assert(interf.isInterface());
436         Iterator i = necessaryTypes.iterator();
437         while (i.hasNext()) {
438             jq_Type t = (jq_Type)i.next();
439             if (!t.isReferenceType()) continue;
440             if (t.isAddressType()) continue;
441             jq_Reference r = (jq_Reference)t;
442             if (!r.implementsInterface(interf)) continue;
443             jq_InstanceMethod m2 = r.getVirtualMethod(i_m.getNameAndDesc());
444             if (m2 == null) {
445                 // error:
446                 if (TRACE) out.println("Error: class "+r+" does not implement interface method "+i_m);
447                 continue;
448             }
449             addNecessaryMethod(m2);
450         }
451     }
452     
453     public void addAllVirtualMethodImplementations(jq_InstanceMethod i_m) {
454         addNecessaryMethod(i_m);
455         addAllVirtualMethodImplementations(i_m.getDeclaringClass(), i_m);
456     }
457     
458     public void addAllVirtualMethodImplementations(jq_Class c, jq_InstanceMethod i_m) {
459         if (!i_m.isOverridden())
460             return;
461         jq_Class[] subclasses = c.getSubClasses();
462         for (int i=0; i<subclasses.length; ++i) {
463             jq_Class subclass = subclasses[i];
464             subclass.prepare();
465             jq_Method m2 = (jq_Method)subclass.getDeclaredMember(i_m.getNameAndDesc());
466             if (m2 != null && !m2.isStatic()) {
467                 addNecessaryMethod(m2);
468             }
469             addAllVirtualMethodImplementations(subclass, i_m);
470         }
471     }
472 
473     // not thread safe.
474     public void trimClass(jq_Class clazz) {
475         Assert._assert(clazz.isPrepared());
476 
477         jq_Class super_class = clazz.getSuperclass();
478         if (super_class != null)
479             trimClass(super_class);
480 
481         Set instantiatedTypes = getInstantiatedTypes();
482         Set necessaryFields = getNecessaryFields();
483         Set necessaryMethods = getNecessaryMethods();
484         
485         Iterator it = clazz.getMembers().iterator();
486         while (it.hasNext()) {
487             jq_Member m = (jq_Member)it.next();
488             if (m instanceof jq_Field) {
489                 if (!necessaryFields.contains(m)) {
490                     if (TRACE) out.println("Eliminating field: "+m);
491                     it.remove();
492                 }
493             } else {
494                 Assert._assert(m instanceof jq_Method);
495                 if (!necessaryMethods.contains(m)) {
496                     if (TRACE) out.println("Eliminating method: "+m);
497                     it.remove();
498                 }
499             }
500         }
501 
502         int n;
503         n=0;
504         jq_InstanceField[] declared_instance_fields = clazz.getDeclaredInstanceFields();
505         for (int i=0; i<declared_instance_fields.length; ++i) {
506             jq_InstanceField f = declared_instance_fields[i];
507             f.unprepare();
508             if (necessaryMethods.contains(f)) ++n;
509         }
510         jq_InstanceField[] ifs = new jq_InstanceField[n];
511         for (int i=0, j=-1; j<n-1; ++i) {
512             jq_InstanceField f = declared_instance_fields[i];
513             if (necessaryFields.contains(f)) {
514                 ifs[++j] = f;
515                 ++jq_Class.NumOfIFieldsKept;
516             } else {
517                 if (TRACE) out.println("Eliminating instance field: "+f);
518                 ++jq_Class.NumOfIFieldsEliminated;
519             }
520         }
521         clazz.setDeclaredInstanceFields(ifs);
522         
523         jq_StaticField[] static_fields = clazz.getDeclaredStaticFields();
524         int static_data_size=0;
525         n=0; 
526         for (int i=0; i<static_fields.length; ++i) {
527             jq_StaticField f = static_fields[i];
528             f.unprepare();
529             if (necessaryFields.contains(f)) ++n;
530         }
531         jq_StaticField[] sfs = new jq_StaticField[n];
532         for (int i=0, j=-1; j<n-1; ++i) {
533             jq_StaticField f = static_fields[i];
534             if (necessaryFields.contains(f)) {
535                 sfs[++j] = f;
536                 static_data_size += f.getWidth();
537                 ++jq_Class.NumOfSFieldsKept;
538             }
539             else {
540                 if (TRACE) out.println("Eliminating static field: "+f);
541                 ++jq_Class.NumOfSFieldsEliminated;
542             }
543         }
544         clazz.setDeclaredStaticFields(sfs);
545 
546         n=0;
547         jq_InstanceMethod[] declared_instance_methods = clazz.getDeclaredInstanceMethods();
548         for (int i=0; i<declared_instance_methods.length; ++i) {
549             jq_InstanceMethod f = declared_instance_methods[i];
550             f.unprepare();
551             f.clearOverrideFlags();
552             if (necessaryMethods.contains(f)) ++n;
553         }
554         jq_InstanceMethod[] ims = new jq_InstanceMethod[n];
555         for (int i=0, j=-1; j<n-1; ++i) {
556             jq_InstanceMethod f = declared_instance_methods[i];
557             if (necessaryMethods.contains(f)) {
558                 ims[++j] = f;
559                 ++jq_Class.NumOfIMethodsKept;
560             } else {
561                 if (BootstrapRootSet.TRACE) BootstrapRootSet.out.println("Eliminating instance method: "+f);
562                 ++jq_Class.NumOfIMethodsEliminated;
563             }
564         }
565         clazz.setDeclaredInstanceMethods(ims);
566         
567         n=0;
568         jq_StaticMethod[] static_methods = clazz.getDeclaredStaticMethods();
569         for (int i=0; i<static_methods.length; ++i) {
570             jq_StaticMethod f = static_methods[i];
571             f.unprepare();
572             if (necessaryMethods.contains(f)) ++n;
573         }
574         jq_StaticMethod[] sms = new jq_StaticMethod[n];
575         for (int i=0, j=-1; j<n-1; ++i) {
576             jq_StaticMethod f = static_methods[i];
577             if (necessaryMethods.contains(f)) {
578                 sms[++j] = f;
579                 ++jq_Class.NumOfSMethodsKept;
580             } else {
581                 if (BootstrapRootSet.TRACE) BootstrapRootSet.out.println("Eliminating static method: "+f);
582                 ++jq_Class.NumOfSMethodsEliminated;
583             }
584         }
585         clazz.setDeclaredStaticMethods(sms);
586         
587         /*
588         n=0;
589         for (int i=0; i<declared_interfaces.length; ++i) {
590             jq_Class f = declared_interfaces[i];
591             if (instantiatedTypes.contains(f)) ++n;
592         }
593         jq_Class[] is = new jq_Class[n];
594         for (int i=0, j=-1; j<n-1; ++i) {
595             jq_Class f = declared_interfaces[i];
596             if (instantiatedTypes.contains(f))
597                 is[++j] = f;
598             else
599                 if (trim.TRACE) trim.out.println("Eliminating interface: "+f);
600         }
601         declared_interfaces = is;
602         */
603         
604         clazz.getCP().trim(necessaryFields, necessaryMethods);
605         
606         clazz.prepare();
607     }
608 }