📄 classparser.java
字号:
/* * FindBugs - Find Bugs in Java programs * Copyright (C) 2006, University of Maryland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */package edu.umd.cs.findbugs.classfile.engine;import java.io.DataInputStream;import java.io.IOException;import java.util.TreeSet;import edu.umd.cs.findbugs.classfile.ClassDescriptor;import edu.umd.cs.findbugs.classfile.FieldDescriptor;import edu.umd.cs.findbugs.classfile.IClassConstants;import edu.umd.cs.findbugs.classfile.ICodeBaseEntry;import edu.umd.cs.findbugs.classfile.InvalidClassFileFormatException;import edu.umd.cs.findbugs.classfile.MethodDescriptor;import edu.umd.cs.findbugs.classfile.analysis.ClassInfo;import edu.umd.cs.findbugs.classfile.analysis.ClassNameAndSuperclassInfo;import edu.umd.cs.findbugs.util.ClassName;/** * Parse a class to extract symbolic information. * see <a href=http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html"> http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html </a> * * @author David Hovemeyer */public class ClassParser { static class Constant { int tag; Object[] data; Constant(int tag, Object[] data) { this.tag = tag; this.data = data; } } private DataInputStream in; private ClassDescriptor expectedClassDescriptor; private ICodeBaseEntry codeBaseEntry; private Constant[] constantPool; /** * Constructor. * * @param in the DataInputStream to read class data from * @param expectedClassDescriptor ClassDescriptor expected: null if unknown * @param codeBaseEntry codebase entry class is loaded from */ public ClassParser( DataInputStream in, ClassDescriptor expectedClassDescriptor, ICodeBaseEntry codeBaseEntry) { this.in = in; this.expectedClassDescriptor = expectedClassDescriptor; this.codeBaseEntry = codeBaseEntry; } /** * Parse the class data into a ClassNameAndSuperclassInfo object containing * (some of) the class's symbolic information. * * @param classInfo a ClassNameAndSuperclassInfo object to be filled in with (some of) * the class's symbolic information * @throws InvalidClassFileFormatException */ public void parse(ClassNameAndSuperclassInfo classInfo) throws InvalidClassFileFormatException { try { int magic = in.readInt(); int major_version = in.readUnsignedShort(); int minor_version = in.readUnsignedShort(); int constant_pool_count = in.readUnsignedShort(); constantPool = new Constant[constant_pool_count]; for (int i = 1; i < constantPool.length; i++) { constantPool[i] = readConstant(); if (constantPool[i].tag == IClassConstants.CONSTANT_Double || constantPool[i].tag == IClassConstants.CONSTANT_Long) { // Double and Long constants take up two constant pool entries ++i; } } int access_flags = in.readUnsignedShort(); int this_class = in.readUnsignedShort(); ClassDescriptor thisClassDescriptor = getClassDescriptor(this_class); int super_class = in.readUnsignedShort(); ClassDescriptor superClassDescriptor = getClassDescriptor(super_class); int interfaces_count = in.readUnsignedShort(); if (interfaces_count < 0) { throw new InvalidClassFileFormatException(expectedClassDescriptor, codeBaseEntry); } ClassDescriptor[] interfaceDescriptorList = new ClassDescriptor[interfaces_count]; for (int i = 0; i < interfaceDescriptorList.length; i++) { interfaceDescriptorList[i] = getClassDescriptor(in.readUnsignedShort()); } classInfo.setClassDescriptor(thisClassDescriptor); classInfo.setSuperclassDescriptor(superClassDescriptor); classInfo.setInterfaceDescriptorList(interfaceDescriptorList); classInfo.setCodeBaseEntry(codeBaseEntry); classInfo.setAccessFlags(access_flags); } catch (IOException e) { throw new InvalidClassFileFormatException(expectedClassDescriptor, codeBaseEntry, e); } } /** * Parse the class data into a ClassInfo object containing * (some of) the class's symbolic information. * * @param classInfo a ClassInfo object to be filled in with (some of) * the class's symbolic information * @throws InvalidClassFileFormatException */ public void parse(ClassInfo classInfo) throws InvalidClassFileFormatException { parse((ClassNameAndSuperclassInfo) classInfo); try { int fields_count = in.readUnsignedShort(); if (fields_count < 0 ) { throw new InvalidClassFileFormatException(expectedClassDescriptor, codeBaseEntry); } FieldDescriptor[] fieldDescriptorList = new FieldDescriptor[fields_count]; for (int i = 0; i < fields_count; i++) { fieldDescriptorList[i] = readField(classInfo.getClassDescriptor()); } int methods_count = in.readUnsignedShort(); if (methods_count < 0) { throw new InvalidClassFileFormatException(expectedClassDescriptor, codeBaseEntry); } MethodDescriptor[] methodDescriptorList = new MethodDescriptor[methods_count]; for (int i = 0; i < methods_count; i++) { methodDescriptorList[i] = readMethod(classInfo.getClassDescriptor()); } // Extract all references to other classes, // both CONSTANT_Class entries and also referenced method // signatures. ClassDescriptor[] referencedClassDescriptorList = extractReferencedClasses(); classInfo.setFieldDescriptorList(fieldDescriptorList); classInfo.setMethodDescriptorList(methodDescriptorList); classInfo.setReferencedClassDescriptorList(referencedClassDescriptorList); } catch (IOException e) { throw new InvalidClassFileFormatException(expectedClassDescriptor, codeBaseEntry, e); } } /** * Extract references to other classes. * * @return array of ClassDescriptors of referenced classes * @throws InvalidClassFileFormatException */ private ClassDescriptor[] extractReferencedClasses() throws InvalidClassFileFormatException { TreeSet<ClassDescriptor> referencedClassSet = new TreeSet<ClassDescriptor>(); for (Constant constant : constantPool) { if (constant == null) { continue; } if (constant.tag == IClassConstants.CONSTANT_Class) { String className = getUtf8String((Integer)constant.data[0]); if (className.indexOf('[') >= 0) { extractReferencedClassesFromSignature(referencedClassSet, className); } else if (ClassName.isValidClassName(className)) { referencedClassSet.add(new ClassDescriptor(className)); } } else if (constant.tag == IClassConstants.CONSTANT_Methodref || constant.tag == IClassConstants.CONSTANT_Fieldref || constant.tag == IClassConstants.CONSTANT_InterfaceMethodref) { // Get the target class name String className = getClassName((Integer) constant.data[0]); extractReferencedClassesFromSignature(referencedClassSet, className); // Parse signature to extract class names String signature = getSignatureFromNameAndType((Integer)constant.data[1]); extractReferencedClassesFromSignature(referencedClassSet, signature); } } ClassDescriptor[] referencedClassDescriptorList = referencedClassSet.toArray(new ClassDescriptor[referencedClassSet.size()]); return referencedClassDescriptorList; } /** * @param referencedClassSet * @param signature */ private void extractReferencedClassesFromSignature(TreeSet<ClassDescriptor> referencedClassSet, String signature) { while (signature.length() > 0) { int start = signature.indexOf('L'); if (start < 0) { break; } signature = signature.substring(start); int end = signature.indexOf(';'); if (end < 0) { break; } String className = signature.substring(1, end); if (ClassName.isValidClassName(className)) { referencedClassSet.add(new ClassDescriptor(className)); } signature = signature.substring(end + 1); } } // 8: UTF-8 string // I: int // F: float // L: long // D: double // i: 2-byte constant pool index private static final String[] CONSTANT_FORMAT_MAP = { null, "8", // 1: CONSTANT_Utf8
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -