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();
}
}
网友评论