View Javadoc

1   /*
2    * Copyright  2000-2004 The Apache Software Foundation
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License"); 
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License. 
15   *
16   */
17  package org.apache.bcel.classfile;
18  
19  import java.io.ByteArrayOutputStream;
20  import java.io.DataOutputStream;
21  import java.io.File;
22  import java.io.FileOutputStream;
23  import java.io.IOException;
24  import java.io.OutputStream;
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.Set;
28  import java.util.StringTokenizer;
29  import java.util.TreeSet;
30  import org.apache.bcel.Constants;
31  import org.apache.bcel.generic.Type;
32  import org.apache.bcel.util.BCELComparator;
33  import org.apache.bcel.util.ClassQueue;
34  import org.apache.bcel.util.SyntheticRepository;
35  
36  /***
37   * Represents a Java class, i.e., the data structures, constant pool,
38   * fields, methods and commands contained in a Java .class file.
39   * See <a href="ftp://java.sun.com/docs/specs/">JVM specification</a> for details.
40   * The intent of this class is to represent a parsed or otherwise existing
41   * class file.  Those interested in programatically generating classes
42   * should see the <a href="../generic/ClassGen.html">ClassGen</a> class.
43  
44   * @version $Id: JavaClass.java 386056 2006-03-15 11:31:56Z tcurdt $
45   * @see org.apache.bcel.generic.ClassGen
46   * @author  <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
47   */
48  public class JavaClass extends AccessFlags implements Cloneable, Node, Comparable {
49  
50      private String file_name;
51      privateong> String package_name;
52      private String source_file_name = "<Unknown>";
53      private int class_name_index;
54      private int superclass_name_index;
55      private String class_name;
56      private String superclass_name;
57      private int major, minor; // Compiler version
58      private ConstantPool constant_pool; // Constant pool
59      private int[] interfaces; // implemented interfaces
60      private String[] interface_names;
61      private Field[] fields; // Fields, i.e., variables of class
62      private Method[] methods; // methods defined in the class
63      private Attribute[] attributes; // attributes defined in the class
64      private byte source = HEAP; // Generated in memory
65      public static final byte HEAP = 1;
66      public static final byte FILE = 2;
67      public static final byte ZIP = 3;
68      static boolean debug = false; // Debugging on/off
69      static char sep = '/'; // directory separator
70      private static BCELComparator _cmp = new BCELComparator() {
71  
72          public boolean equals( Object o1, Object o2 ) {
73              JavaClass THIS = (JavaClass) o1;
74              JavaClass THAT = (JavaClass) o2;
75              return THIS.getClassName().equals(THAT.getClassName());
76          }
77  
78  
79          public int hashCode( Object o ) {
80              JavaClass THIS = (JavaClass) o;
81              return THIS.getClassName().hashCode();
82          }
83      };
84      /***
85       * In cases where we go ahead and create something,
86       * use the default SyntheticRepository, because we
87       * don't know any better.
88       */
89      private transient org.apache.bcel.util.Repository repository = SyntheticRepository
90              .getInstance();
91  
92  
93      /***
94       * Constructor gets all contents as arguments.
95       *
96       * @param class_name_index Index into constant pool referencing a
97       * ConstantClass that represents this class.
98       * @param superclass_name_index Index into constant pool referencing a
99       * ConstantClass that represents this class's superclass.
100      * @param file_name File name
101      * @param major Major compiler version
102      * @param minor Minor compiler version
103      * @param access_flags Access rights defined by bit flags
104      * @param constant_pool Array of constants
105      * @param interfaces Implemented interfaces
106      * @param fields Class fields
107      * @param methods Class methods
108      * @param attributes Class attributes
109      * @param source Read from file or generated in memory?
110      */
111     public JavaClass(int class_name_index, int superclass_name_index, String file_name, int major,
112             int minor, int access_flags, ConstantPool constant_pool, int[] interfaces,
113             Field[] fields, Method[] methods, Attribute[] attributes, byte source) {
114         if (interfaces == null) {
115             interfaces = new int[0];
116         }
117         if (attributes == null) {
118             attributes = new Attribute[0];
119         }
120         if (fields == null) {
121             fields = new Field[0];
122         }
123         if (methods == null) {
124             methods = new Method[0];
125         }
126         this.class_name_index = class_name_index;
127         this.superclass_name_index = superclass_name_index;
128         this.file_name = file_name;
129         this.major = major;
130         this.minor = minor;
131         this.access_flags = access_flags;
132         this.constant_pool = constant_pool;
133         this.interfaces = interfaces;
134         this.fields = fields;
135         this.methods = methods;
136         this.attributes = attributes;
137         this.source = source;
138         // Get source file name if available
139         for (int i = 0; i < attributes.length; i++) {
140             if (attributes[i] instanceof SourceFile) {
141                 source_file_name = ((SourceFile) attributes[i]).getSourceFileName();
142                 break;
143             }
144         }
145         /* According to the specification the following entries must be of type
146          * `ConstantClass' but we check that anyway via the 
147          * `ConstPool.getConstant' method.
148          */
149         class_name = constant_pool.getConstantString(class_name_index, Constants.CONSTANT_Class);
150         class_name = Utility.compactClassName(class_name, false);
151         int index = class_name.lastIndexOf('.');
152         if (index < 0) {
153             package_name =/package-summary.html">strong>_name = "";
154         } else {
155             package_name = class_name/substring(0, index)/package-summary.html">strong>_name = class_name.substring(0, index);
156         }
157         if (superclass_name_index > 0) {
158             // May be zero -> class is java.lang.Object
159             superclass_name = constant_pool.getConstantString(superclass_name_index,
160                     Constants.CONSTANT_Class);
161             superclass_name = Utility.compactClassName(superclass_name, false);
162         } else {
163             superclass_name = "java.lang.Object";
164         }
165         interface_names = new String[interfaces.length];
166         for (int i = 0; i < interfaces.length; i++) {
167             String str = constant_pool.getConstantString(interfaces[i], Constants.CONSTANT_Class);
168             interface_names[i] = Utility.compactClassName(str, false);
169         }
170     }
171 
172 
173     /***
174      * Constructor gets all contents as arguments.
175      *
176      * @param class_name_index Class name
177      * @param superclass_name_index Superclass name
178      * @param file_name File name
179      * @param major Major compiler version
180      * @param minor Minor compiler version
181      * @param access_flags Access rights defined by bit flags
182      * @param constant_pool Array of constants
183      * @param interfaces Implemented interfaces
184      * @param fields Class fields
185      * @param methods Class methods
186      * @param attributes Class attributes
187      */
188     public JavaClass(int class_name_index, int superclass_name_index, String file_name, int major,
189             int minor, int access_flags, ConstantPool constant_pool, int[] interfaces,
190             Field[] fields, Method[] methods, Attribute[] attributes) {
191         this(class_name_index, superclass_name_index, file_name, major, minor, access_flags,
192                 constant_pool, interfaces, fields, methods, attributes, HEAP);
193     }
194 
195 
196     /***
197      * Called by objects that are traversing the nodes of the tree implicitely
198      * defined by the contents of a Java class. I.e., the hierarchy of methods,
199      * fields, attributes, etc. spawns a tree of objects.
200      *
201      * @param v Visitor object
202      */
203     public void accept( Visitor v ) {
204         v.visitJavaClass(this);
205     }
206 
207 
208     /* Print debug information depending on `JavaClass.debug'
209      */
210     static final void Debug( String str ) {
211         if (debug) {
212             System.out.println(str);
213         }
214     }
215 
216 
217     /*** 
218      * Dump class to a file.
219      *
220      * @param file Output file
221      * @throws IOException
222      */
223     public void dump( File file ) throws IOException {
224         String parent = file.getParent();
225         if (parent != null) {
226             File dir = new File(parent);
227             dir.mkdirs();
228         }
229         DataOutputStream dos = null;
230         try {
231             dos = new DataOutputStream(new FileOutputStream(file));
232             dump(dos);
233         } finally {
234             if (dos != null) {
235                 dos.close();
236             }
237         }
238     }
239 
240 
241     /*** 
242      * Dump class to a file named file_name.
243      *
244      * @param _file_name Output file name
245      * @exception IOException
246      */
247     public void dump( String _file_name ) throws IOException {
248         dump(new File(_file_name));
249     }
250 
251 
252     /***
253      * @return class in binary format
254      */
255     public byte[] getBytes() {
256         ByteArrayOutputStream s = new ByteArrayOutputStream();
257         DataOutputStream ds = new DataOutputStream(s);
258         try {
259             dump(ds);
260         } catch (IOException e) {
261             e.printStackTrace();
262         } finally {
263             try {
264                 ds.close();
265             } catch (IOException e2) {
266                 e2.printStackTrace();
267             }
268         }
269         return s.toByteArray();
270     }
271 
272 
273     /***
274      * Dump Java class to output stream in binary format.
275      *
276      * @param file Output stream
277      * @exception IOException
278      */
279     public void dump( OutputStream file ) throws IOException {
280         dump(new DataOutputStream(file));
281     }
282 
283 
284     /***
285      * Dump Java class to output stream in binary format.
286      *
287      * @param file Output stream
288      * @exception IOException
289      */
290     public void dump( DataOutputStream file ) throws IOException {
291         file.writeInt(0xcafebabe);
292         file.writeShort(minor);
293         file.writeShort(major);
294         constant_pool.dump(file);
295         file.writeShort(access_flags);
296         file.writeShort(class_name_index);
297         file.writeShort(superclass_name_index);
298         file.writeShort(interfaces.length);
299         for (int i = 0; i < interfaces.length; i++) {
300             file.writeShort(interfaces[i]);
301         }
302         file.writeShort(fields.length);
303         for (int i = 0; i < fields.length; i++) {
304             fields[i].dump(file);
305         }
306         file.writeShort(methods.length);
307         for (int i = 0; i < methods.length; i++) {
308             methods[i].dump(file);
309         }
310         if (attributes != null) {
311             file.writeShort(attributes.length);
312             for (int i = 0; i < attributes.length; i++) {
313                 attributes[i].dump(file);
314             }
315         } else {
316             file.writeShort(0);
317         }
318         file.flush();
319     }
320 
321 
322     /***
323      * @return Attributes of the class.
324      */
325     public Attribute[] getAttributes() {
326         return attributes;
327     }
328 
329 
330     /***
331      * @return Class name.
332      */
333     public String getClassName() {
334         return class_name;
335     }
336 
337 
338     /***
339      * @return Package name.
340      */
341     public String getPackageName() {
342         return</strong> package_name;
343     }
344 
345 
346     /***
347      * @return Class name index.
348      */
349     public int getClassNameIndex() {
350         return class_name_index;
351     }
352 
353 
354     /***
355      * @return Constant pool.
356      */
357     public ConstantPool getConstantPool() {
358         return constant_pool;
359     }
360 
361 
362     /***
363      * @return Fields, i.e., variables of the class. Like the JVM spec
364      * mandates for the classfile format, these fields are those specific to
365      * this class, and not those of the superclass or superinterfaces.
366      */
367     public Field[] getFields() {
368         return fields;
369     }
370 
371 
372     /***
373      * @return File name of class, aka SourceFile attribute value
374      */
375     public String getFileName() {
376         return file_name;
377     }
378 
379 
380     /***
381      * @return Names of implemented interfaces.
382      */
383     public String[] getInterfaceNames() {
384         return interface_names;
385     }
386 
387 
388     /***
389      * @return Indices in constant pool of implemented interfaces.
390      */
391     public int[] getInterfaceIndices() {
392         return interfaces;
393     }
394 
395 
396     /***
397      * @return Major number of class file version.
398      */
399     public int getMajor() {
400         return major;
401     }
402 
403 
404     /***
405      * @return Methods of the class.
406      */
407     public Method[] getMethods() {
408         return methods;
409     }
410 
411 
412     /***
413      * @return A org.apache.bcel.classfile.Method corresponding to
414      * java.lang.reflect.Method if any
415      */
416     public Method getMethod( java.lang.reflect.Method m ) {
417         for (int i = 0; i < methods.length; i++) {
418             Method method = methods[i];
419             if (m.getName().equals(method.getName()) && (m.getModifiers() == method.getModifiers())
420                     && Type.getSignature(m).equals(method.getSignature())) {
421                 return method;
422             }
423         }
424         return null;
425     }
426 
427 
428     /***
429      * @return Minor number of class file version.
430      */
431     public int getMinor() {
432         return minor;
433     }
434 
435 
436     /***
437      * @return sbsolute path to file where this class was read from
438      */
439     public String getSourceFileName() {
440         return source_file_name;
441     }
442 
443 
444     /***
445      * @return Superclass name.
446      */
447     public String getSuperclassName() {
448         return superclass_name;
449     }
450 
451 
452     /***
453      * @return Class name index.
454      */
455     public int getSuperclassNameIndex() {
456         return superclass_name_index;
457     }
458 
459     static {
460         // Debugging ... on/off
461         debug = Boolean.getBoolean("JavaClass.debug");
462         // Get path separator either / or \ usually
463         String _sep = System.getProperty("file.separator");
464         if (_sep != null) {
465             try {
466                 JavaClass.sep = _sep.charAt(0);
467             } catch (StringIndexOutOfBoundsException e) {
468             } // Never reached
469         }
470     }
471 
472 
473     /***
474      * @param attributes .
475      */
476     public void setAttributes( Attribute[] attributes ) {
477         this.attributes = attributes;
478     }
479 
480 
481     /***
482      * @param class_name .
483      */
484     public void setClassName( String class_name ) {
485         this.class_name = class_name;
486     }
487 
488 
489     /***
490      * @param class_name_index .
491      */
492     public void setClassNameIndex( int class_name_index ) {
493         this.class_name_index = class_name_index;
494     }
495 
496 
497     /***
498      * @param constant_pool .
499      */
500     public void setConstantPool( ConstantPool constant_pool ) {
501         this.constant_pool = constant_pool;
502     }
503 
504 
505     /***
506      * @param fields .
507      */
508     public void setFields( Field[] fields ) {
509         this.fields = fields;
510     }
511 
512 
513     /***
514      * Set File name of class, aka SourceFile attribute value
515      */
516     public void setFileName( String file_name ) {
517         this.file_name = file_name;
518     }
519 
520 
521     /***
522      * @param interface_names .
523      */
524     public void setInterfaceNames( String[] interface_names ) {
525         this.interface_names = interface_names;
526     }
527 
528 
529     /***
530      * @param interfaces .
531      */
532     public void setInterfaces( int[] interfaces ) {
533         this.interfaces = interfaces;
534     }
535 
536 
537     /***
538      * @param major .
539      */
540     public void setMajor( int major ) {
541         this.major = major;
542     }
543 
544 
545     /***
546      * @param methods .
547      */
548     public void setMethods( Method[] methods ) {
549         this.methods = methods;
550     }
551 
552 
553     /***
554      * @param minor .
555      */
556     public void setMinor( int minor ) {
557         this.minor = minor;
558     }
559 
560 
561     /***
562      * Set absolute path to file this class was read from.
563      */
564     public void setSourceFileName( String source_file_name ) {
565         this.source_file_name = source_file_name;
566     }
567 
568 
569     /***
570      * @param superclass_name .
571      */
572     public void setSuperclassName( String superclass_name ) {
573         this.superclass_name = superclass_name;
574     }
575 
576 
577     /***
578      * @param superclass_name_index .
579      */
580     public void setSuperclassNameIndex( int superclass_name_index ) {
581         this.superclass_name_index = superclass_name_index;
582     }
583 
584 
585     /***
586      * @return String representing class contents.
587      */
588     public String toString() {
589         String access = Utility.accessToString(access_flags, true);
590         access = access.equals("") ? "" : (access + " ");
591         StringBuffer buf = new StringBuffer(128);
592         buf.append(access).append(Utility.classOrInterface(access_flags)).append(" ").append(
593                 class_name).append(" extends ").append(
594                 Utility.compactClassName(superclass_name, false)).append('\n');
595         int size = interfaces.length;
596         if (size > 0) {
597             buf.append("implements\t\t");
598             for (int i = 0; i < size; i++) {
599                 buf.append(interface_names[i]);
600                 if (i < size - 1) {
601                     buf.append(", ");
602                 }
603             }
604             buf.append('\n');
605         }
606         buf.append("filename\t\t").append(file_name).append('\n');
607         buf.append("compiled from\t\t").append(source_file_name).append('\n');
608         buf.append("compiler version\t").append(major).append(".").append(minor).append('\n');
609         buf.append("access flags\t\t").append(access_flags).append('\n');
610         buf.append("constant pool\t\t").append(constant_pool.getLength()).append(" entries\n");
611         buf.append("ACC_SUPER flag\t\t").append(isSuper()).append("\n");
612         if (attributes.length > 0) {
613             buf.append("\nAttribute(s):\n");
614             for (int i = 0; i < attributes.length; i++) {
615                 buf.append(indent(attributes[i]));
616             }
617         }
618         if (fields.length > 0) {
619             buf.append("\n").append(fields.length).append(" fields:\n");
620             for (int i = 0; i < fields.length; i++) {
621                 buf.append("\t").append(fields[i]).append('\n');
622             }
623         }
624         if (methods.length > 0) {
625             buf.append("\n").append(methods.length).append(" methods:\n");
626             for (int i = 0; i < methods.length; i++) {
627                 buf.append("\t").append(methods[i]).append('\n');
628             }
629         }
630         return buf.toString();
631     }
632 
633 
634     private static final String indent( Object obj ) {
635         StringTokenizer tok = new StringTokenizer(obj.toString(), "\n");
636         StringBuffer buf = new StringBuffer();
637         while (tok.hasMoreTokens()) {
638             buf.append("\t").append(tok.nextToken()).append("\n");
639         }
640         return buf.toString();
641     }
642 
643 
644     /***
645      * @return deep copy of this class
646      */
647     public JavaClass copy() {
648         JavaClass c = null;
649         try {
650             c = (JavaClass) clone();
651             c.constant_pool = constant_pool.copy();
652             c.interfaces = (int[]) interfaces.clone();
653             c.interface_names = (String[]) interface_names.clone();
654             c.fields = new Field[fields.length];
655             for (int i = 0; i < fields.length; i++) {
656                 c.fields[i] = fields[i].copy(c.constant_pool);
657             }
658             c.methods = new Method[methods.length];
659             for (int i = 0; i < methods.length; i++) {
660                 c.methods[i] = methods[i].copy(c.constant_pool);
661             }
662             c.attributes = new Attribute[attributes.length];
663             for (int i = 0; i < attributes.length; i++) {
664                 c.attributes[i] = attributes[i].copy(c.constant_pool);
665             }
666         } catch (CloneNotSupportedException e) {
667         }
668         return c;
669     }
670 
671 
672     public final boolean isSuper() {
673         return (access_flags & Constants.ACC_SUPER) != 0;
674     }
675 
676 
677     public final boolean isClass() {
678         return (access_flags & Constants.ACC_INTERFACE) == 0;
679     }
680 
681 
682     /*** @return returns either HEAP (generated), FILE, or ZIP
683      */
684     public final byte getSource() {
685         return source;
686     }
687 
688 
689     /********************** New repository functionality *********************/
690     /***
691      * Gets the ClassRepository which holds its definition. By default
692      * this is the same as SyntheticRepository.getInstance();
693      */
694     public org.apache.bcel.util.Repository getRepository() {
695         return repository;
696     }
697 
698 
699     /***
700      * Sets the ClassRepository which loaded the JavaClass.
701      * Should be called immediately after parsing is done.
702      */
703     public void setRepository( org.apache.bcel.util.Repository repository ) {
704         this.repository = repository;
705     }
706 
707 
708     /*** Equivalent to runtime "instanceof" operator.
709      *
710      * @return true if this JavaClass is derived from the super class
711      * @throws ClassNotFoundException if superclasses or superinterfaces
712      *   of this object can't be found
713      */
714     public final boolean instanceOf( JavaClass super_class ) throws ClassNotFoundException {
715         if (this.equals(super_class)) {
716             return true;
717         }
718         JavaClass[] super_classes = getSuperClasses();
719         for (int i = 0; i < super_classes.length; i++) {
720             if (super_classes[i].equals(super_class)) {
721                 return true;
722             }
723         }
724         if (super_class.isInterface()) {
725             return implementationOf(super_class);
726         }
727         return false;
728     }
729 
730 
731     /***
732      * @return true, if this class is an implementation of interface inter
733      * @throws ClassNotFoundException if superclasses or superinterfaces
734      *   of this class can't be found
735      */
736     public boolean implementationOf( JavaClass inter ) throws ClassNotFoundException {
737         if (!inter.isInterface()) {
738             throw new IllegalArgumentException(inter.getClassName() + " is no interface");
739         }
740         if (this.equals(inter)) {
741             return true;
742         }
743         JavaClass[] super_interfaces = getAllInterfaces();
744         for (int i = 0; i < super_interfaces.length; i++) {
745             if (super_interfaces[i].equals(inter)) {
746                 return true;
747             }
748         }
749         return false;
750     }
751 
752 
753     /***
754      * @return the superclass for this JavaClass object, or null if this
755      * is java.lang.Object
756      * @throws ClassNotFoundException if the superclass can't be found
757      */
758     public JavaClass getSuperClass() throws ClassNotFoundException {
759         if ("java.lang.Object".equals(getClassName())) {
760             return null;
761         }
762         return repository.loadClass(getSuperclassName());
763     }
764 
765 
766     /***
767      * @return list of super classes of this class in ascending order, i.e.,
768      * java.lang.Object is always the last element
769      * @throws ClassNotFoundException if any of the superclasses can't be found
770      */
771     public JavaClass[] getSuperClasses() throws ClassNotFoundException {
772         JavaClass clazz = this;
773         List allSuperClasses = new ArrayList();
774         for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) {
775             allSuperClasses.add(clazz);
776         }
777         return (JavaClass[]) allSuperClasses.toArray(new JavaClass[allSuperClasses.size()]);
778     }
779 
780 
781     /***
782      * Get interfaces directly implemented by this JavaClass.
783      */
784     public JavaClass[] getInterfaces() throws ClassNotFoundException {
785         String[] _interfaces = getInterfaceNames();
786         JavaClass[] classes = new JavaClass[_interfaces.length];
787         for (int i = 0; i < _interfaces.length; i++) {
788             classes[i] = repository.loadClass(_interfaces[i]);
789         }
790         return classes;
791     }
792 
793 
794     /***
795      * Get all interfaces implemented by this JavaClass (transitively).
796      */
797     public JavaClass[] getAllInterfaces() throws ClassNotFoundException {
798         ClassQueue queue = new ClassQueue();
799         Set allInterfaces = new TreeSet();
800         queue.enqueue(this);
801         while (!queue.empty()) {
802             JavaClass clazz = queue.dequeue();
803             JavaClass souper = clazz.getSuperClass();
804             JavaClass[] _interfaces = clazz.getInterfaces();
805             if (clazz.isInterface()) {
806                 allInterfaces.add(clazz);
807             } else {
808                 if (souper != null) {
809                     queue.enqueue(souper);
810                 }
811             }
812             for (int i = 0; i < _interfaces.length; i++) {
813                 queue.enqueue(_interfaces[i]);
814             }
815         }
816         return (JavaClass[]) allInterfaces.toArray(new JavaClass[allInterfaces.size()]);
817     }
818 
819 
820     /***
821      * @return Comparison strategy object
822      */
823     public static BCELComparator getComparator() {
824         return _cmp;
825     }
826 
827 
828     /***
829      * @param comparator Comparison strategy object
830      */
831     public static void setComparator( BCELComparator comparator ) {
832         _cmp = comparator;
833     }
834 
835 
836     /***
837      * Return value as defined by given BCELComparator strategy.
838      * By default two JavaClass objects are said to be equal when
839      * their class names are equal.
840      * 
841      * @see java.lang.Object#equals(java.lang.Object)
842      */
843     public boolean equals( Object obj ) {
844         return _cmp.equals(this, obj);
845     }
846 
847 
848     /***
849      * Return the natural ordering of two JavaClasses.
850      * This ordering is based on the class name
851      */
852     public int compareTo( Object obj ) {
853         return getClassName().compareTo(((JavaClass) obj).getClassName());
854     }
855 
856 
857     /***
858      * Return value as defined by given BCELComparator strategy.
859      * By default return the hashcode of the class name.
860      * 
861      * @see java.lang.Object#hashCode()
862      */
863     public int hashCode() {
864         return _cmp.hashCode(this);
865     }
866 }