Javac 生成字节码文件

Javac 生成字节码文件

Javac 生成 Class 文件的过程,主要类是 com.sun.tools.javac.jvm.ClassWriter.

Class 文件的结构

Class 文件中存储了两种数据类型:无符号数和表。

表是用来描述有层次关系的复合结构的数据.

而无符号数可以用来标识一个具体结构的类型,或者还可以表示数量及属性长度等.

在 Javac 的 ByteBuffer 类中提供了写入基本类型的常用方法,如 appendByte() 方法

ByteBuffer 对象表示一个具体的缓冲,主要通过 elems 来保存缓冲的内容,Javac 在向 Class 文件中写入字节码时不会一个字节一个字节地写,而是先写入 ByteBuffer 缓冲中,然后一次性写入 Class 文件来提高写入的效率。

/** Write constant pool to pool buffer.
    *  Note: during writing, constant pool
    *  might grow since some parts of constants still need to be entered.
    */
void writePool(Pool pool) throws PoolOverflow, StringOverflow {
    int poolCountIdx = poolbuf.length;
    poolbuf.appendChar(0); // 追加一个 0 值, 表示不引用任何一个常量池项
    int i = 1;
    while (i < pool.pp) { // writePool() 方法循环读取 pool.pool 数组中存储的所有常量池信息,并按照 JVMS 规定的常量池项的格式存储到 poolbuf 缓冲中
        Object value = pool.pool[i];
        Assert.checkNonNull(value);
        if (value instanceof Method || value instanceof Variable)
            value = ((DelegatedSymbol)value).getUnderlyingSymbol();

        if (value instanceof MethodSymbol) {
            MethodSymbol m = (MethodSymbol)value;
            if (!m.isDynamic()) {
                poolbuf.appendByte((m.owner.flags() & INTERFACE) != 0
                            ? CONSTANT_InterfaceMethodref
                            : CONSTANT_Methodref);
                poolbuf.appendChar(pool.put(m.owner));
                poolbuf.appendChar(pool.put(nameType(m)));
            } else {
                //invokedynamic
                DynamicMethodSymbol dynSym = (DynamicMethodSymbol)m;
                MethodHandle handle = new MethodHandle(dynSym.bsmKind, dynSym.bsm, types);
                DynamicMethod dynMeth = new DynamicMethod(dynSym, types);
                bootstrapMethods.put(dynMeth, handle);
                //init cp entries
                pool.put(names.BootstrapMethods);
                pool.put(handle);
                for (Object staticArg : dynSym.staticArgs) {
                    pool.put(staticArg);
                }
                poolbuf.appendByte(CONSTANT_InvokeDynamic);
                poolbuf.appendChar(bootstrapMethods.size() - 1);
                poolbuf.appendChar(pool.put(nameType(dynSym)));
            }
        } else if (value instanceof VarSymbol) {
            VarSymbol v = (VarSymbol)value;
            poolbuf.appendByte(CONSTANT_Fieldref);
            poolbuf.appendChar(pool.put(v.owner));
            poolbuf.appendChar(pool.put(nameType(v)));
        } else if (value instanceof Name) { // 当 value 是 Name 对象时会写入一个 CONSTANT_Utf8_info 常量池项
            poolbuf.appendByte(CONSTANT_Utf8); // 值为 1
            byte[] bs = ((Name)value).toUtf();
            poolbuf.appendChar(bs.length); // 写入使用 2 个字节表示的字符串长度
            poolbuf.appendBytes(bs, 0, bs.length); // 保存具体的字符串信息
            if (bs.length> Pool.MAX_STRING_LENGTH)
                throw new StringOverflow(value.toString());
        } else if (value instanceof ClassSymbol) {
            ClassSymbol c = (ClassSymbol)value;
            if (c.owner.kind == TYP) pool.put(c.owner);
            poolbuf.appendByte(CONSTANT_Class);
            if (c.type.hasTag(ARRAY)) {
                poolbuf.appendChar(pool.put(typeSig(c.type)));
            } else {
                poolbuf.appendChar(pool.put(names.fromUtf(externalize(c.flatname))));
                enterInner(c);
            }
        } else if (value instanceof NameAndType) {
            NameAndType nt = (NameAndType)value;
            poolbuf.appendByte(CONSTANT_NameandType);
            poolbuf.appendChar(pool.put(nt.name));
            poolbuf.appendChar(pool.put(typeSig(nt.uniqueType.type)));
        } else if (value instanceof Integer) {
            poolbuf.appendByte(CONSTANT_Integer);
            poolbuf.appendInt(((Integer)value).intValue());
        } else if (value instanceof Long) {
            poolbuf.appendByte(CONSTANT_Long);
            poolbuf.appendLong(((Long)value).longValue());
            i++;
        } else if (value instanceof Float) {
            poolbuf.appendByte(CONSTANT_Float);
            poolbuf.appendFloat(((Float)value).floatValue());
        } else if (value instanceof Double) {
            poolbuf.appendByte(CONSTANT_Double);
            poolbuf.appendDouble(((Double)value).doubleValue());
            i++;
        } else if (value instanceof String) {
            poolbuf.appendByte(CONSTANT_String);
            poolbuf.appendChar(pool.put(names.fromString((String)value)));
        } else if (value instanceof UniqueType) {
            Type type = ((UniqueType)value).type;
            if (type instanceof MethodType) {
                poolbuf.appendByte(CONSTANT_MethodType);
                poolbuf.appendChar(pool.put(typeSig((MethodType)type)));
            } else {
                if (type.hasTag(CLASS)) enterInner((ClassSymbol)type.tsym);
                poolbuf.appendByte(CONSTANT_Class);
                poolbuf.appendChar(pool.put(xClassName(type)));
            }
        } else if (value instanceof MethodHandle) {
            MethodHandle ref = (MethodHandle)value;
            poolbuf.appendByte(CONSTANT_MethodHandle);
            poolbuf.appendByte(ref.refKind);
            poolbuf.appendChar(pool.put(ref.refSym));
        } else {
            Assert.error("writePool" + value);
        }
        i++;
    }
    if (pool.pp> Pool.MAX_ENTRIES)
        throw new PoolOverflow();
    putChar(poolbuf, poolCountIdx, pool.pp); // 将 pool.pp 写入 ByteBuffer 对象的 elems 数组中, 具体就是写入到下标为 poolCountIdx 与 poolCountIdx+1 的位置,poolCountIdx 的值是 8,要在 Class 文件的第 8 个和第 9 个字节中写入常量池项的数量,而 pool.pp 保存了常量池项的数量
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FlyingZCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值