美文网首页
asm 与 javac constant pool (常量池)

asm 与 javac constant pool (常量池)

作者: onedam | 来源:发表于2022-04-07 15:35 被阅读0次
4efee0a62513c22b281e793b089e53c.png

constant pool 内部的排序谁研究过. java1.8的会排的乱七八糟. 但clojure 用asm生成的类 排的 后面的引用前面的. 顺序不乱.


99bf08a4610a2507a5f6db7bd1750b8.png 773454737ca2b4a3c41983012f259bf.png

初步感觉是. javac 里面是递归搞得. 所以前面的可以依赖后面的.


4811e4d76381baef1d73da1a399d125.png

asm 则遇到没有的引用 先去建立. 所有依赖都是前后有序的.

asm SymbolTable (类似hashset) 关键工具类. 里面的数据结构 如果不明白 hashmap 实现原理.
理解起来有点困难
https://www.bilibili.com/video/BV1YP4y1W71c 这个视频讲的较为清楚.

/**
   * An entry of a SymbolTable. This concrete and private subclass of {@link Symbol} adds two fields
   * which are only used inside SymbolTable, to implement hash sets of symbols (in order to avoid
   * duplicate symbols). See {@link #entries}.
   这里实现了一个hashset  保证常量池不重复. 
   */
  private static class Entry extends Symbol {

    /** The hash code of this entry. */
    final int hashCode;

    /**
     * Another entry (and so on recursively) having the same hash code (modulo the size of {@link
     * #entries}) as this one.
     */
    Entry next;


 /**
   * A hash set of all the entries in this SymbolTable (this includes the constant pool entries, the
   * bootstrap method entries and the type table entries). Each {@link Entry} instance is stored at
   * the array index given by its hash code modulo the array size. If several entries must be stored
   * at the same array index, they are linked together via their {@link Entry#next} field. The
   * factory methods of this class make sure that this table does not contain duplicated entries.
   */

// 这里包含了 所有的 constantspool 的条目. 其中有坑的https://www.jianshu.com/p/307ac4b8b93e
  private Entry[] entries;     
image.png

void writePool(Pool pool) throws PoolOverflow, StringOverflow {
     

2022年4月7日 class constant pool 写法分析
E:\clojure\luminusweb\jdk\src\jdk.compiler\share\classes\com\sun\tools\javac\jvm\ClassWriter.java


1525 行 
  public void writeClassFile(OutputStream out, ClassSymbol c)

poolbuf.appendInt(JAVA_MAGIC);
        if (preview.isEnabled() && preview.usesPreview(c.sourcefile)) {
            poolbuf.appendChar(ClassFile.PREVIEW_MINOR_VERSION);
        } else {
            poolbuf.appendChar(target.minorVersion);
        }
        poolbuf.appendChar(target.majorVersion);

然后使用    poolWriter.writePool(out);   // 帮助类 看起来更清晰了 .

核心算法实现类 WriteablePoolHelper

 final WriteablePoolHelper pool;
 int putName(Name name) {
        return pool.writeIfNeeded(name);
    }
class WriteablePoolHelper {

        /** Pool entries. */
        private final Map<Object, Integer> keysToPos = new HashMap<>(64);

        final ByteBuffer poolbuf = new ByteBuffer(POOL_BUF_SIZE);

        int currentIndex = 1;

        ArrayDeque<PoolConstant> todo = new ArrayDeque<>();

        String overflowString = null;

        private <P extends PoolConstant> int writeIfNeeded(P p) {
            Object key = p.poolKey(types);
            Integer index = keysToPos.get(key);
            if (index == null) {
                keysToPos.put(key, index = currentIndex++);
                boolean first = todo.isEmpty();
                todo.addLast(p);
                if (first) {
                    while (!todo.isEmpty()) {
                        writeConstant(todo.peekFirst());
                        todo.removeFirst();
                    }
                }
            }
            return index;
        }

        void writeConstant(PoolConstant c) {
            int tag = c.poolTag();
            switch (tag) {
                case ClassFile.CONSTANT_Class: {
                    Type ct = (Type)c;
                    Name name = ct.hasTag(ARRAY) ?
                            typeSig(ct) :
                            names.fromUtf(externalize(ct.tsym.flatName()));
                    poolbuf.appendByte(tag);
                    poolbuf.appendChar(putName(name));
                    if (ct.hasTag(CLASS)) {
                        enterInner((ClassSymbol)ct.tsym);
                    }
                    break;
                }
                case ClassFile.CONSTANT_Utf8: {
                    Name name = (Name)c;
                    poolbuf.appendByte(tag);
                    byte[] bs = name.toUtf();
                    poolbuf.appendChar(bs.length);
                    poolbuf.appendBytes(bs, 0, bs.length);
                    if (overflowString == null && bs.length > MAX_STRING_LENGTH) {
                        //report error only once
                        overflowString = new String(bs);
                    }
                    break;
                }
                case ClassFile.CONSTANT_InterfaceMethodref:
                case ClassFile.CONSTANT_Methodref:
                case ClassFile.CONSTANT_Fieldref: {
                    Symbol sym = (Symbol)c;
                    poolbuf.appendByte(tag);
                    poolbuf.appendChar(putClass((ClassSymbol)sym.owner));
                    poolbuf.appendChar(putNameAndType(sym));
                    break;
                }
                case ClassFile.CONSTANT_Package: {
                    PackageSymbol pkg = (PackageSymbol)c;
                    Name pkgName = names.fromUtf(externalize(pkg.flatName()));
                    poolbuf.appendByte(tag);
                    poolbuf.appendChar(putName(pkgName));
                    break;
                }
                case ClassFile.CONSTANT_Module: {
                    ModuleSymbol mod = (ModuleSymbol)c;
                    int modName = putName(mod.name);
                    poolbuf.appendByte(mod.poolTag());
                    poolbuf.appendChar(modName);
                    break;
                }
                case ClassFile.CONSTANT_Integer:
                    poolbuf.appendByte(tag);
                    poolbuf.appendInt((int)((BasicConstant)c).data);
                    break;
                case ClassFile.CONSTANT_Float:
                    poolbuf.appendByte(tag);
                    poolbuf.appendFloat((float)((BasicConstant)c).data);
                    break;
                case ClassFile.CONSTANT_Long:
                    currentIndex++;
                    poolbuf.appendByte(tag);
                    poolbuf.appendLong((long)((BasicConstant)c).data);
                    break;
                case ClassFile.CONSTANT_Double:
                    currentIndex++;
                    poolbuf.appendByte(tag);
                    poolbuf.appendDouble((double)((BasicConstant)c).data);
                    break;
                case ClassFile.CONSTANT_MethodHandle: {
                    MethodHandleSymbol h = (MethodHandleSymbol)c;
                    poolbuf.appendByte(tag);
                    poolbuf.appendByte(h.referenceKind());
                    poolbuf.appendChar(putMember(h.baseSymbol()));
                    break;
                }
                case ClassFile.CONSTANT_MethodType: {
                    Type.MethodType mt = (Type.MethodType)c;
                    poolbuf.appendByte(tag);
                    poolbuf.appendChar(putDescriptor(mt.baseType()));
                    break;
                }
                case ClassFile.CONSTANT_String: {
                    Name utf = names.fromString((String)((BasicConstant)c).data);
                    poolbuf.appendByte(tag);
                    poolbuf.appendChar(putName(utf));
                    break;
                }
                case ClassFile.CONSTANT_NameandType: {
                    NameAndType nt = (NameAndType)c;
                    poolbuf.appendByte(tag);
                    poolbuf.appendChar(putName(nt.name));
                    poolbuf.appendChar(putDescriptor(nt.type));
                    break;
                }
                case ClassFile.CONSTANT_InvokeDynamic: {
                    DynamicMethodSymbol d = (DynamicMethodSymbol)c;
                    poolbuf.appendByte(tag);
                    poolbuf.appendChar(makeBootstrapEntry(d));
                    poolbuf.appendChar(putNameAndType(d));
                    break;
                }
                case ClassFile.CONSTANT_Dynamic: {
                    Symbol.DynamicVarSymbol d = (Symbol.DynamicVarSymbol)c;
                    poolbuf.appendByte(tag);
                    poolbuf.appendChar(makeBootstrapEntry(d));
                    poolbuf.appendChar(putNameAndType(d));
                    break;
                }
                default:
                    throw new AssertionError("Unexpected constant tag: " + tag);
            }
        }

        void reset() {
            keysToPos.clear();
            currentIndex = 1;
            todo.clear();
            overflowString = null;
            poolbuf.reset();
        }
    }

相关文章

网友评论

      本文标题:asm 与 javac constant pool (常量池)

      本文链接:https://www.haomeiwen.com/subject/zuqrkltx.html