运行时常量池中的符号引用/String.intern() /ldc指令

运行时常量池,之前放在方法区(永久代)中,1.8之后被转移到元空间,放到了native memory中。

具体的数据结构是:(看对象的内存布局,句柄访问还是对象头中保存指向类的元数据的指针,这里以对象头markword之后保存指向元数据指针为例)对象有一个指向类元数据的指针,指向的这个数据结构InstanceClass,

InstanceKlass有一个指针指向一个constantPool数据结构(运行时常量池),这个数据结构是一个数组,数组里面元素的排列方式和class文件中是一样的(从1号常量到N号常量),只不过值有变化,7-18里面保存的是数字,根据规则拆开指向的是1-6类型的序号,而1-6类型保存的指向symbol对象的指针,在class文件中,1-6指向的内容是class文件单独的,而在运行时常量池中,指向的symbol对象是可以共享的,能做到这一点是因为在引用symbol对象之前,要经过一个hashTable存取(这个和我们从hashmap中get push的原理差不多),这个hashTable叫symbolTable,存放在元空间,而每个symbol对象存放在堆中。

在ldc命令(以类型1的utf-8为例)中,如果ldc后面的两个字节指向的符号引用没有被解析过,指向的必然是symbol对象在常量池中的序号,那么需要首先去StringTable(和symbolTable一样的一个hashTable,存放在元空间中,保存着指向堆中的String对象的引用)找equal自己指向的symbol对象的String对象,如果找到,把自己后面两个字节保存这个String对象的引用,然后把这个string对象的引用放入栈顶。如果没找到,从刚才说的symbol对象中(下面的红色字体)解析出String对象(这里要先创建一个char数组对象,棕色字体),并放到字符串常量池(StringTable)中(粉色字体,intern方法),然后两个字节替换成引用,入栈。

而String.intern()方法是根据一个String对象去StringTable中找,找到了,方法返回里面对象的引用,找不到,放进去,返回引用。所以返回值是不是原String看之前有没有

 

oop StringTable::intern(Symbol* symbol, TRAPS) {
  if (symbol == NULL) return NULL;
  ResourceMark rm(THREAD);
  int length;
  jchar* chars = symbol->as_unicode(length);  // 从 Symbol 中解析出字符串字面量
  Handle string;
  oop result = intern(string, chars, length, CHECK_NULL); // 调用又一个同名方法
  return result;
}

 字符串拼接,字节码分析可以见这篇文章:https://www.cnblogs.com/Kidezyq/p/8040338.html

转载于:https://www.cnblogs.com/chuliang/p/8447698.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值