classdecoder.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 531 行 · 第 1/2 页

JAVA
531
字号
/**
 * $Id: ClassDecoder.java,v 1.9 2004/02/24 08:04:15 epr Exp $
 */

package org.jnode.vm.classmgr;

import org.jnode.system.BootLog;

public final class ClassDecoder {

    // ------------------------------------------
    // VM ClassLoader Code
    // ------------------------------------------

    private static char[] ConstantValueAttrName;

    private static char[] CodeAttrName;

    private static char[] ExceptionsAttrName;

    private static char[] LineNrTableAttrName;

    //private static final Logger log = Logger.getLogger(ClassDecoder.class);

    private static final void cl_init() {
        if (ConstantValueAttrName == null) {
            ConstantValueAttrName = "ConstantValue".toCharArray();
        }
        if (CodeAttrName == null) {
            CodeAttrName = "Code".toCharArray();
        }
        if (ExceptionsAttrName == null) {
            ExceptionsAttrName = "Exceptions".toCharArray();
        }
        if (LineNrTableAttrName == null) {
            LineNrTableAttrName = "LineNumberTable".toCharArray();
        }
    }

    /**
     * Convert a class-file image into a Class object. Steps taken in this
     * phase: 1. Decode the class-file image (CLS_LS_DECODED) 2. Load the
     * super-class of the loaded class (CLS_LS_DEFINED) 3. Link the class so
     * that the VMT is set and the offset of the non-static fields are set
     * correctly.
     * 
     * @param className
     * @param data
     * @param offset
     * @param class_image_length
     * @param rejectNatives
     * @param clc
     * @return The defined class
     */
    public static final VmType defineClass(String className, byte[] data,
            int offset, int class_image_length, boolean rejectNatives,
            VmClassLoader clc) {
        cl_init();
        VmType cls = decodeClass(data, offset, class_image_length,
                rejectNatives, clc);
        return cls;
    }

    /**
     * Decode a given class.
     * 
     * @param data
     * @param offset
     * @param class_image_length
     * @param rejectNatives
     * @param clc
     * @return The decoded class
     * @throws ClassFormatError
     */
    private static final VmType decodeClass(byte[] data, int offset,
            int class_image_length, boolean rejectNatives, VmClassLoader clc)
            throws ClassFormatError {
        if (data == null) { throw new ClassFormatError(
                "ClassDecoder.decodeClass: data==null"); }
        final ClassReader reader = new ClassReader(data, offset,
                class_image_length);
        final VmStatics statics = clc.getStatics();
        final int slotSize = clc.getArchitecture().getReferenceSize();

        final int magic = reader.readu4();
        if (magic != 0xCAFEBABE) { throw new ClassFormatError("invalid magic"); }
        final int min_version = reader.readu2();
        final int maj_version = reader.readu2();

        if (false) {
            BootLog.debug("Class file version " + maj_version + ";"
                    + min_version);
        }

        final int cpcount = reader.readu2();
        // allocate enough space for the CP
        final byte[] tags = new byte[ cpcount];
        final VmCP cp = new VmCP(cpcount);
        for (int i = 1; i < cpcount; i++) {
            final int tag = reader.readu1();
            tags[ i] = (byte) tag;
            switch (tag) {
            case 1:
                // Utf8
                cp.setUTF8(i, new String(reader.readUTF()));
                break;
            case 3:
                // int
                cp.setInt(i, reader.readu4());
                break;
            case 4:
                // float
                cp.setInt(i, reader.readu4());
                break;
            case 5:
                // long
                cp.setLong(i, reader.readu8());
                i++;
                break;
            case 6:
                // double
                cp.setLong(i, reader.readu8());
                i++;
                break;
            case 7:
                // class
                cp.setConstClass(i, new VmConstClass(cp, reader.readu2()));
                break;
            case 8:
                // String
                cp.setInt(i, reader.readu2());
                break;
            case 9:
                // Fieldref
                {
                    final int clsIdx = reader.readu2();
                    final int ntIdx = reader.readu2();
                    cp.setConstFieldRef(i, new VmConstFieldRef(cp, clsIdx,
                            ntIdx));
                }
                break;
            case 10:
                // Methodref
                {
                    final int clsIdx = reader.readu2();
                    final int ntIdx = reader.readu2();
                    cp.setConstMethodRef(i, new VmConstMethodRef(cp, clsIdx,
                            ntIdx));
                }
                break;
            case 11:
                // IMethodref
                {
                    final int clsIdx = reader.readu2();
                    final int ntIdx = reader.readu2();
                    cp.setConstIMethodRef(i, new VmConstIMethodRef(cp, clsIdx,
                            ntIdx));
                }
                break;
            case 12:
                // Name and Type
                {
                    final int nIdx = reader.readu2();
                    final int dIdx = reader.readu2();
                    cp.setConstNameAndType(i, new VmConstNameAndType(cp, nIdx,
                            dIdx));
                }
                break;
            default:
                throw new ClassFormatError("Invalid constantpool tag: "
                        + tags[ i]);
            }
        }

        // Now patch the required entries
        for (int i = 1; i < cpcount; i++) {
            switch (tags[ i]) {
            case 8:
                // String
                final int idx = cp.getInt(i);
                final int staticsIdx = statics.allocConstantStringField(cp
                        .getUTF8(idx));
                cp.setString(i, new VmConstString(staticsIdx));
                break;
            }
        }

        final int classModifiers = reader.readu2();

        final VmConstClass this_class = cp.getConstClass(reader.readu2());
        final String clsName = this_class.getClassName();

        final VmConstClass super_class = cp.getConstClass(reader.readu2());
        final String superClassName;
        if (super_class != null) {
            superClassName = super_class.getClassName();
        } else {
            superClassName = null;
        }

        // Allocate the class object
        final VmType cls;
        if (Modifier.isInterface(classModifiers)) {
            cls = new VmInterfaceClass(clsName, superClassName, clc,
                    classModifiers);
        } else {
            cls = new VmNormalClass(clsName, superClassName, clc,
                    classModifiers);
        }
        cls.setCp(cp);

        // Interface table
        readInterfaces(reader, cls, cp);

        // Field table
        readFields(reader, cls, cp, statics, slotSize);

        // Method Table
        readMethods(reader, rejectNatives, cls, cp, statics);

        return cls;
    }

    /**
     * Read the interfaces table
     * 
     * @param reader
     * @param cls
     * @param cp
     */
    private static void readInterfaces(ClassReader reader, VmType cls, VmCP cp) {
        final int icount = reader.readu2();
        if (icount > 0) {
            final VmImplementedInterface[] itable = new VmImplementedInterface[ icount];
            for (int i = 0; i < icount; i++) {
                final VmConstClass icls = cp.getConstClass(reader.readu2());
                itable[ i] = new VmImplementedInterface(icls.getClassName());
            }
            cls.setInterfaceTable(itable);
        }
    }

    /**
     * Read the fields table
     * 
     * @param reader
     * @param cls
     * @param cp
     * @param slotSize
     */
    private static void readFields(ClassReader reader, VmType cls, VmCP cp,
            VmStatics statics, int slotSize) {
        final int fcount = reader.readu2();
        if (fcount > 0) {
            final VmField[] ftable = new VmField[ fcount];

            int objectSize = 0;
            for (int i = 0; i < fcount; i++) {
                final boolean wide;
                int modifiers = reader.readu2();
                final String name = cp.getUTF8(reader.readu2());
                final String signature = cp.getUTF8(reader.readu2());
                switch (signature.charAt(0)) {
                case 'J':
                case 'D':
                    modifiers = modifiers | Modifier.ACC_WIDE;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?