alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (ClassWriter.java)

This example Java source code file (ClassWriter.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

classwriter, constantvalue, debug, exceptions, ioexception, jvm_constant_double, jvm_constant_long, jvm_constant_utf8, localvariabletable, short, string, symbol, util

The ClassWriter.java Java example source code

/*
 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot.tools.jcore;

import java.io.*;
import java.util.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.utilities.*;

public class ClassWriter implements /* imports */ ClassConstants
{
    public static final boolean DEBUG = false;

    protected void debugMessage(String message) {
        System.out.println(message);
    }

    protected InstanceKlass     klass;
    protected DataOutputStream  dos;
    protected ConstantPool      cpool;

    // Map between class name to index of type CONSTANT_Class
    protected Map<String, Short> classToIndex = new HashMap();

    // Map between any modified UTF-8 and it's constant pool index.
    protected Map<String, Short> utf8ToIndex = new HashMap();

    // constant pool index for attribute names.

    protected short  _sourceFileIndex;
    protected short  _innerClassesIndex;
    protected short  _syntheticIndex;
    protected short  _deprecatedIndex;
    protected short  _constantValueIndex;
    protected short  _codeIndex;
    protected short  _exceptionsIndex;
    protected short  _lineNumberTableIndex;
    protected short  _localVariableTableIndex;
    protected short  _signatureIndex;

    protected static int extractHighShortFromInt(int val) {
        // must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc.
        return (val >> 16) & 0xFFFF;
    }

    protected static int extractLowShortFromInt(int val) {
        // must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc.
        return val & 0xFFFF;
    }

    public ClassWriter(InstanceKlass kls, OutputStream os) {
        klass = kls;
        dos = new DataOutputStream(os);
        cpool = klass.getConstants();
    }

    public void write() throws IOException {
        if (DEBUG) debugMessage("class name = " + klass.getName().asString());

        // write magic
        dos.writeInt(0xCAFEBABE);

        writeVersion();
        writeConstantPool();
        writeClassAccessFlags();
        writeThisClass();
        writeSuperClass();
        writeInterfaces();
        writeFields();
        writeMethods();
        writeClassAttributes();

        // flush output
        dos.flush();
    }

    protected void writeVersion() throws IOException {
        dos.writeShort((short)klass.minorVersion());
        dos.writeShort((short)klass.majorVersion());
    }

    protected void writeIndex(int index) throws IOException {
        if (index == 0) throw new InternalError();
        dos.writeShort(index);
    }

    protected void writeConstantPool() throws IOException {
        final U1Array tags = cpool.getTags();
        final long len = tags.length();
        dos.writeShort((short) len);

        if (DEBUG) debugMessage("constant pool length = " + len);

        int ci = 0; // constant pool index

        // collect all modified UTF-8 Strings from Constant Pool

        for (ci = 1; ci < len; ci++) {
            int cpConstType = tags.at(ci);
            if(cpConstType == JVM_CONSTANT_Utf8) {
                Symbol sym = cpool.getSymbolAt(ci);
                utf8ToIndex.put(sym.asString(), new Short((short) ci));
            }
            else if(cpConstType == JVM_CONSTANT_Long ||
                      cpConstType == JVM_CONSTANT_Double) {
                ci++;
            }
        }

        // remember index of attribute name modified UTF-8 strings

        // class attributes
        Short sourceFileIndex = (Short) utf8ToIndex.get("SourceFile");
        _sourceFileIndex = (sourceFileIndex != null)? sourceFileIndex.shortValue() : 0;
        if (DEBUG) debugMessage("SourceFile index = " + _sourceFileIndex);

        Short innerClassesIndex = (Short) utf8ToIndex.get("InnerClasses");
        _innerClassesIndex = (innerClassesIndex != null)? innerClassesIndex.shortValue() : 0;
        if (DEBUG) debugMessage("InnerClasses index = " + _innerClassesIndex);

        // field attributes
        Short constantValueIndex = (Short) utf8ToIndex.get("ConstantValue");
        _constantValueIndex = (constantValueIndex != null)?
                                          constantValueIndex.shortValue() : 0;
        if (DEBUG) debugMessage("ConstantValue index = " + _constantValueIndex);

        Short syntheticIndex = (Short) utf8ToIndex.get("Synthetic");
        _syntheticIndex = (syntheticIndex != null)? syntheticIndex.shortValue() : 0;
        if (DEBUG) debugMessage("Synthetic index = " + _syntheticIndex);

        Short deprecatedIndex = (Short) utf8ToIndex.get("Deprecated");
        _deprecatedIndex = (deprecatedIndex != null)? deprecatedIndex.shortValue() : 0;
        if (DEBUG) debugMessage("Deprecated index = " + _deprecatedIndex);

        // method attributes
        Short codeIndex = (Short) utf8ToIndex.get("Code");
        _codeIndex = (codeIndex != null)? codeIndex.shortValue() : 0;
        if (DEBUG) debugMessage("Code index = " + _codeIndex);

        Short exceptionsIndex = (Short) utf8ToIndex.get("Exceptions");
        _exceptionsIndex = (exceptionsIndex != null)? exceptionsIndex.shortValue() : 0;
        if (DEBUG) debugMessage("Exceptions index = " + _exceptionsIndex);

        // Short syntheticIndex = (Short) utf8ToIndex.get("Synthetic");
        // Short deprecatedIndex = (Short) utf8ToIndex.get("Deprecated");

        // Code attributes
        Short lineNumberTableIndex = (Short) utf8ToIndex.get("LineNumberTable");
        _lineNumberTableIndex = (lineNumberTableIndex != null)?
                                       lineNumberTableIndex.shortValue() : 0;
        if (DEBUG) debugMessage("LineNumberTable index = " + _lineNumberTableIndex);

        Short localVariableTableIndex = (Short) utf8ToIndex.get("LocalVariableTable");
        _localVariableTableIndex = (localVariableTableIndex != null)?
                                       localVariableTableIndex.shortValue() : 0;
        if (DEBUG) debugMessage("LocalVariableTable index = " + _localVariableTableIndex);

        Short signatureIdx = (Short) utf8ToIndex.get("Signature");
        _signatureIndex = (signatureIdx != null)? signatureIdx.shortValue() : 0;
        if (DEBUG) debugMessage("Signature index = " + _signatureIndex);

        for(ci = 1; ci < len; ci++) {
            int cpConstType = tags.at(ci);
            // write cp_info
            // write constant type
            switch(cpConstType) {
                case JVM_CONSTANT_Utf8: {
                     dos.writeByte(cpConstType);
                     Symbol sym = cpool.getSymbolAt(ci);
                     dos.writeShort((short)sym.getLength());
                     dos.write(sym.asByteArray());
                     if (DEBUG) debugMessage("CP[" + ci + "] = modified UTF-8 " + sym.asString());
                     break;
                }

                case JVM_CONSTANT_Unicode:
                     throw new IllegalArgumentException("Unicode constant!");

                case JVM_CONSTANT_Integer:
                     dos.writeByte(cpConstType);
                     dos.writeInt(cpool.getIntAt(ci));
                     if (DEBUG) debugMessage("CP[" + ci + "] = int " + cpool.getIntAt(ci));
                     break;

                case JVM_CONSTANT_Float:
                     dos.writeByte(cpConstType);
                     dos.writeFloat(cpool.getFloatAt(ci));
                     if (DEBUG) debugMessage("CP[" + ci + "] = float " + cpool.getFloatAt(ci));
                     break;

                case JVM_CONSTANT_Long: {
                     dos.writeByte(cpConstType);
                     long l = cpool.getLongAt(ci);
                     // long entries occupy two pool entries
                     ci++;
                     dos.writeLong(l);
                     break;
                }

                case JVM_CONSTANT_Double:
                     dos.writeByte(cpConstType);
                     dos.writeDouble(cpool.getDoubleAt(ci));
                     // double entries occupy two pool entries
                     ci++;
                     break;

                case JVM_CONSTANT_Class:
                case JVM_CONSTANT_UnresolvedClass:
                case JVM_CONSTANT_UnresolvedClassInError: {
                     dos.writeByte(JVM_CONSTANT_Class);
                     String klassName = cpool.getKlassNameAt(ci).asString();
                     Short s = (Short) utf8ToIndex.get(klassName);
                     classToIndex.put(klassName, new Short((short)ci));
                     dos.writeShort(s.shortValue());
                     if (DEBUG) debugMessage("CP[" + ci  + "] = class " + s);
                     break;
                }

                case JVM_CONSTANT_String: {
                     dos.writeByte(cpConstType);
                     String str = cpool.getUnresolvedStringAt(ci).asString();
                     Short s = (Short) utf8ToIndex.get(str);
                     dos.writeShort(s.shortValue());
                     if (DEBUG) debugMessage("CP[" + ci + "] = string " + s);
                     break;
                }

                // all external, internal method/field references
                case JVM_CONSTANT_Fieldref:
                case JVM_CONSTANT_Methodref:
                case JVM_CONSTANT_InterfaceMethodref: {
                     dos.writeByte(cpConstType);
                     int value = cpool.getIntAt(ci);
                     short klassIndex = (short) extractLowShortFromInt(value);
                     short nameAndTypeIndex = (short) extractHighShortFromInt(value);
                     dos.writeShort(klassIndex);
                     dos.writeShort(nameAndTypeIndex);
                     if (DEBUG) debugMessage("CP[" + ci + "] = ref klass = " +
                           klassIndex + ", N&T = " + nameAndTypeIndex);
                     break;
                }

                case JVM_CONSTANT_NameAndType: {
                     dos.writeByte(cpConstType);
                     int value = cpool.getIntAt(ci);
                     short nameIndex = (short) extractLowShortFromInt(value);
                     short signatureIndex = (short) extractHighShortFromInt(value);
                     dos.writeShort(nameIndex);
                     dos.writeShort(signatureIndex);
                     if (DEBUG) debugMessage("CP[" + ci + "] = N&T name = " + nameIndex
                                        + ", type = " + signatureIndex);
                     break;
                }

                case JVM_CONSTANT_MethodHandle: {
                     dos.writeByte(cpConstType);
                     int value = cpool.getIntAt(ci);
                     byte refKind = (byte) extractLowShortFromInt(value);
                     short memberIndex = (short) extractHighShortFromInt(value);
                     dos.writeByte(refKind);
                     dos.writeShort(memberIndex);
                     if (DEBUG) debugMessage("CP[" + ci + "] = MH kind = " +
                           refKind + ", mem = " + memberIndex);
                     break;
                }

                case JVM_CONSTANT_MethodType: {
                     dos.writeByte(cpConstType);
                     int value = cpool.getIntAt(ci);
                     short refIndex = (short) value;
                     dos.writeShort(refIndex);
                     if (DEBUG) debugMessage("CP[" + ci + "] = MT index = " + refIndex);
                     break;
                }

                case JVM_CONSTANT_InvokeDynamic: {
                     dos.writeByte(cpConstType);
                     int value = cpool.getIntAt(ci);
                     short bsmIndex = (short) extractLowShortFromInt(value);
                     short nameAndTypeIndex = (short) extractHighShortFromInt(value);
                     dos.writeShort(bsmIndex);
                     dos.writeShort(nameAndTypeIndex);
                     if (DEBUG) debugMessage("CP[" + ci + "] = INDY bsm = " +
                           bsmIndex + ", N&T = " + nameAndTypeIndex);
                     break;
                }

                default:
                  throw new InternalError("Unknown tag: " + cpConstType);
            } // switch
        }
    }

    protected void writeClassAccessFlags() throws IOException {
        int flags = (int)(klass.getAccessFlags() & JVM_RECOGNIZED_CLASS_MODIFIERS);
        dos.writeShort((short)flags);
    }

    protected void writeThisClass() throws IOException {
        String klassName = klass.getName().asString();
        Short index = (Short) classToIndex.get(klassName);
        dos.writeShort(index.shortValue());
        if (DEBUG) debugMessage("this class = " + index);
    }

    protected void writeSuperClass() throws IOException {
        Klass superKlass = klass.getSuper();
        if (superKlass != null) { // is not java.lang.Object
            String superName = superKlass.getName().asString();
            Short index = (Short) classToIndex.get(superName);
            if (DEBUG) debugMessage("super class = " + index);
            dos.writeShort(index.shortValue());
        } else {
            dos.writeShort(0); // no super class
        }
    }
    protected void writeInterfaces() throws IOException {
        KlassArray interfaces = klass.getLocalInterfaces();
        final int len = interfaces.length();

        if (DEBUG) debugMessage("number of interfaces = " + len);

        // write interfaces count
        dos.writeShort((short) len);
        for (int i = 0; i < len; i++) {
           Klass k = interfaces.getAt(i);
           Short index = (Short) classToIndex.get(k.getName().asString());
           dos.writeShort(index.shortValue());
           if (DEBUG) debugMessage("\t" + index);
        }
    }

    protected void writeFields() throws IOException {
        final int javaFieldsCount = klass.getJavaFieldsCount();

        // write number of fields
        dos.writeShort((short) javaFieldsCount);

        if (DEBUG) debugMessage("number of fields = " + javaFieldsCount);

        for (int index = 0; index < javaFieldsCount; index++) {
            short accessFlags    = klass.getFieldAccessFlags(index);
            dos.writeShort(accessFlags & (short) JVM_RECOGNIZED_FIELD_MODIFIERS);

            short nameIndex    = klass.getFieldNameIndex(index);
            dos.writeShort(nameIndex);

            short signatureIndex = klass.getFieldSignatureIndex(index);
            dos.writeShort(signatureIndex);
            if (DEBUG) debugMessage("\tfield name = " + nameIndex + ", signature = " + signatureIndex);

            short fieldAttributeCount = 0;
            boolean hasSyn = hasSyntheticAttribute(accessFlags);
            if (hasSyn)
                fieldAttributeCount++;

            short initvalIndex = klass.getFieldInitialValueIndex(index);
            if (initvalIndex != 0)
                fieldAttributeCount++;

            short genSigIndex = klass.getFieldGenericSignatureIndex(index);
            if (genSigIndex != 0)
                fieldAttributeCount++;

            dos.writeShort(fieldAttributeCount);

            // write synthetic, if applicable
            if (hasSyn)
                writeSynthetic();

            if (initvalIndex != 0) {
                writeIndex(_constantValueIndex);
                dos.writeInt(2);
                dos.writeShort(initvalIndex);
                if (DEBUG) debugMessage("\tfield init value = " + initvalIndex);
            }

            if (genSigIndex != 0) {
                writeIndex(_signatureIndex);
                dos.writeInt(2);
                dos.writeShort(genSigIndex);
                if (DEBUG) debugMessage("\tfield generic signature index " + genSigIndex);
            }
        }
    }

    protected boolean isSynthetic(short accessFlags) {
        return (accessFlags & (short) JVM_ACC_SYNTHETIC) != 0;
    }

    protected boolean hasSyntheticAttribute(short accessFlags) {
        // Check if flags have the attribute and if the constant pool contains an entry for it.
        return isSynthetic(accessFlags) && _syntheticIndex != 0;
    }

    protected void writeSynthetic() throws IOException {
        writeIndex(_syntheticIndex);
        dos.writeInt(0);
    }

    protected void writeMethods() throws IOException {
        MethodArray methods = klass.getMethods();
        final int len = methods.length();
        // write number of methods
        dos.writeShort((short) len);
        if (DEBUG) debugMessage("number of methods = " + len);
        for (int m = 0; m < len; m++) {
            writeMethod(methods.at(m));
        }
    }

    protected void writeMethod(Method m) throws IOException {
        long accessFlags = m.getAccessFlags();
        dos.writeShort((short) (accessFlags & JVM_RECOGNIZED_METHOD_MODIFIERS));
        dos.writeShort((short) m.getNameIndex());
        dos.writeShort((short) m.getSignatureIndex());
        if (DEBUG) debugMessage("\tmethod name = " + m.getNameIndex() + ", signature = "
                        + m.getSignatureIndex());

        final boolean isNative = ((accessFlags & JVM_ACC_NATIVE) != 0);
        final boolean isAbstract = ((accessFlags & JVM_ACC_ABSTRACT) != 0);

        short methodAttributeCount = 0;

        final boolean hasSyn = hasSyntheticAttribute((short)accessFlags);
        if (hasSyn)
            methodAttributeCount++;

        final boolean hasCheckedExceptions = m.hasCheckedExceptions();
        if (hasCheckedExceptions)
            methodAttributeCount++;

        final boolean isCodeAvailable = (!isNative) && (!isAbstract);
        if (isCodeAvailable)
            methodAttributeCount++;

        final boolean isGeneric = (m.getGenericSignature() != null);
        if (isGeneric)
            methodAttributeCount++;

        dos.writeShort(methodAttributeCount);
        if (DEBUG) debugMessage("\tmethod attribute count = " + methodAttributeCount);

        if (hasSyn) {
            if (DEBUG) debugMessage("\tmethod is synthetic");
            writeSynthetic();
        }

        if (isCodeAvailable) {
            byte[] code = m.getByteCode();
            short codeAttrCount = 0;
            int codeSize  = 2           /* max_stack   */ +
                            2           /* max_locals  */ +
                            4           /* code_length */ +
                            code.length /* code        */ +
                            2           /* exp. table len.  */ +
                            2           /* code attr. count */;

            boolean hasExceptionTable = m.hasExceptionTable();
            ExceptionTableElement[] exceptionTable = null;
            int exceptionTableLen = 0;
            if (hasExceptionTable) {
                exceptionTable = m.getExceptionTable();
                exceptionTableLen = exceptionTable.length;
                if (DEBUG) debugMessage("\tmethod has exception table");
                codeSize += exceptionTableLen /* exception table is 4-tuple array */
                                         * (2 /* start_pc     */ +
                                            2 /* end_pc       */ +
                                            2 /* handler_pc   */ +
                                            2 /* catch_type   */);
            }

            boolean hasLineNumberTable = m.hasLineNumberTable();
            LineNumberTableElement[] lineNumberTable = null;
            int lineNumberAttrLen = 0;

            if (hasLineNumberTable) {
                if (DEBUG) debugMessage("\tmethod has line number table");
                lineNumberTable = m.getLineNumberTable();
                if (DEBUG) debugMessage("\t\tline table length = " + lineNumberTable.length);

                lineNumberAttrLen = 2 /* line number table length         */ +
                           lineNumberTable.length * (2 /* start_pc */ + 2 /* line_number */);

                codeSize += 2 /* line number table attr index     */ +
                            4 /* line number table attr length    */ +
                            lineNumberAttrLen;

                if (DEBUG) debugMessage("\t\tline number table attr size = " +
                                              lineNumberAttrLen);

                codeAttrCount++;
            }

            boolean hasLocalVariableTable = m.hasLocalVariableTable();
            LocalVariableTableElement[] localVariableTable = null;
            int localVarAttrLen = 0;

            if (hasLocalVariableTable) {
                if (DEBUG) debugMessage("\tmethod has local variable table");
                localVariableTable = m.getLocalVariableTable();
                if (DEBUG) debugMessage("\t\tlocal variable table length = "
                              + localVariableTable.length);
                localVarAttrLen =
                               2 /* local variable table length      */ +
                               localVariableTable.length * ( 2 /* start_pc          */ +
                                                          2 /* length            */ +
                                                          2 /* name_index        */ +
                                                          2 /* signature_index   */ +
                                                          2 /* variable index    */ );

                if (DEBUG) debugMessage("\t\tlocal variable attr size = " +
                                              localVarAttrLen);

                codeSize += 2 /* local variable table attr index  */ +
                            4 /* local variable table attr length */ +
                            localVarAttrLen;

                codeAttrCount++;
            }

            // fix ConstantPoolCache indices to ConstantPool indices.
            rewriteByteCode(m, code);

            // start writing Code

            writeIndex(_codeIndex);

            dos.writeInt(codeSize);
            if (DEBUG) debugMessage("\tcode attribute length = " + codeSize);

            dos.writeShort((short) m.getMaxStack());
            if (DEBUG) debugMessage("\tmax stack = " + m.getMaxStack());

            dos.writeShort((short) m.getMaxLocals());
            if (DEBUG) debugMessage("\tmax locals = " + m.getMaxLocals());

            dos.writeInt(code.length);
            if (DEBUG) debugMessage("\tcode size = " + code.length);

            dos.write(code);

            // write exception table size
            dos.writeShort((short) exceptionTableLen);
            if (DEBUG) debugMessage("\texception table length = " + exceptionTableLen);

            if (exceptionTableLen != 0) {
                for (int e = 0; e < exceptionTableLen; e++) {
                     dos.writeShort((short) exceptionTable[e].getStartPC());
                     dos.writeShort((short) exceptionTable[e].getEndPC());
                     dos.writeShort((short) exceptionTable[e].getHandlerPC());
                     dos.writeShort((short) exceptionTable[e].getCatchTypeIndex());
                }
            }

            dos.writeShort((short)codeAttrCount);
            if (DEBUG) debugMessage("\tcode attribute count = " + codeAttrCount);

            // write LineNumberTable, if available.
            if (hasLineNumberTable) {
                writeIndex(_lineNumberTableIndex);
                dos.writeInt(lineNumberAttrLen);
                dos.writeShort((short) lineNumberTable.length);
                for (int l = 0; l < lineNumberTable.length; l++) {
                     dos.writeShort((short) lineNumberTable[l].getStartBCI());
                     dos.writeShort((short) lineNumberTable[l].getLineNumber());
                }
            }

            // write LocalVariableTable, if available.
            if (hasLocalVariableTable) {
                writeIndex((short) _localVariableTableIndex);
                dos.writeInt(localVarAttrLen);
                dos.writeShort((short) localVariableTable.length);
                for (int l = 0; l < localVariableTable.length; l++) {
                     dos.writeShort((short) localVariableTable[l].getStartBCI());
                     dos.writeShort((short) localVariableTable[l].getLength());
                     dos.writeShort((short) localVariableTable[l].getNameCPIndex());
                     dos.writeShort((short) localVariableTable[l].getDescriptorCPIndex());
                     dos.writeShort((short) localVariableTable[l].getSlot());
                }
            }
        }

        if (hasCheckedExceptions) {
            CheckedExceptionElement[] exceptions = m.getCheckedExceptions();
            writeIndex(_exceptionsIndex);

            int attrSize = 2 /* number_of_exceptions */ +
                           exceptions.length * 2 /* exception_index */;
            dos.writeInt(attrSize);
            dos.writeShort(exceptions.length);
            if (DEBUG) debugMessage("\tmethod has " + exceptions.length
                                        +  " checked exception(s)");
            for (int e = 0; e < exceptions.length; e++) {
                 short cpIndex = (short) exceptions[e].getClassCPIndex();
                 dos.writeShort(cpIndex);
            }
        }

        if (isGeneric) {
           writeGenericSignature(m.getGenericSignature().asString());
        }
    }

    protected void rewriteByteCode(Method m, byte[] code) {
        ByteCodeRewriter r = new ByteCodeRewriter(m, cpool, code);
        r.rewrite();
    }

    protected void writeGenericSignature(String signature) throws IOException {
        writeIndex(_signatureIndex);
        if (DEBUG) debugMessage("signature attribute = " + _signatureIndex);
        dos.writeInt(2);
        Short index = (Short) utf8ToIndex.get(signature);
        dos.writeShort(index.shortValue());
        if (DEBUG) debugMessage("generic signature = " + index);
    }

    protected void writeClassAttributes() throws IOException {
        final long flags = klass.getAccessFlags();
        final boolean hasSyn = hasSyntheticAttribute((short) flags);

        // check for source file
        short classAttributeCount = 0;

        if (hasSyn)
            classAttributeCount++;

        Symbol sourceFileName = klass.getSourceFileName();
        if (sourceFileName != null)
            classAttributeCount++;

        Symbol genericSignature = klass.getGenericSignature();
        if (genericSignature != null)
            classAttributeCount++;

        U2Array innerClasses = klass.getInnerClasses();
        final int numInnerClasses = (int) (innerClasses.length() / 4);
        if (numInnerClasses != 0)
            classAttributeCount++;

        dos.writeShort(classAttributeCount);
        if (DEBUG) debugMessage("class attribute count = " + classAttributeCount);

        if (hasSyn)
            writeSynthetic();

        // write SourceFile, if any
        if (sourceFileName != null) {
            writeIndex(_sourceFileIndex);
            if (DEBUG) debugMessage("source file attribute = " + _sourceFileIndex);
            dos.writeInt(2);
            Short index = (Short) utf8ToIndex.get(sourceFileName.asString());
            dos.writeShort(index.shortValue());
            if (DEBUG) debugMessage("source file name = " + index);
        }

        // write Signature, if any
        if (genericSignature != null) {
            writeGenericSignature(genericSignature.asString());
        }

        // write inner classes, if any
        if (numInnerClasses != 0) {
            writeIndex(_innerClassesIndex);
            final int innerAttrLen = 2 /* number_of_inner_classes */ +
                                     numInnerClasses * (
                                                 2 /* inner_class_info_index */ +
                                                 2 /* outer_class_info_index */ +
                                                 2 /* inner_class_name_index */ +
                                                 2 /* inner_class_access_flags */);
            dos.writeInt(innerAttrLen);

            dos.writeShort(numInnerClasses);
            if (DEBUG) debugMessage("class has " + numInnerClasses + " inner class entries");

            for (int index = 0; index < numInnerClasses * 4; index++) {
                dos.writeShort(innerClasses.at(index));
            }
        }
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java ClassWriter.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.