zoukankan      html  css  js  c++  java
  • 运行时常量池中的符号引用/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结构体在自己的class对应的运行时常量池中的序号,那么需要首先去StringTable(和symbolTable一样的一个hashTable,存放在元空间中,保存着指向堆中的String对象的引用)找和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

    String a = new String("a");
    String b = new String("a");

    这一段代码中a和b是不相等的

    String a = "a";
    String b = "a";

    这第二段代码中a和b是相等的

    先看第二段代码,反编译成字节码是这样的:

    可以看到,第0行,ldc根据a这个字符串,新建了一个String对象,并把地址存入1号本地变量位,第3行,再次根据a这个字符串创建String对象,这时候发现字符串常量池中有了,直接返回引用,并在第5行存到2号本地变量位,之后如果比较1和2变量的时候,肯定是相等的。

    再看第一段代码,反编译成字节码是这样的:

    可以看到,先是new方法新建一个String对象,复制一份到栈顶,再用ldc生成一个String对象到栈顶,第6行是调用string的构造方法,给栈底的String对象赋初始值。可见虽然两个ldc命令返回同一个String对象,但是a和b并不指向ldc返回的这个String对象,而是指向新的两个对象,而这两个对象的value值都是ldc返回值的value值。

  • 相关阅读:
    vulcanjs 包类型
    vulcanjs schemas&& collections
    vulcanjs 核心架构概念
    vulcanjs 开源工具方便快速开发react graphql meteor 应用
    ory Oathkeeper Ecosystem
    ory Oathkeeper docker-compose 安装运行
    benthos stream nats 集成试用
    benthos 几个方便的帮助命令
    benthos 通过配置文件配置 stream 说明
    benthos 通过rest api 配置 stream 说明
  • 原文地址:https://www.cnblogs.com/chuliang/p/8447698.html
Copyright © 2011-2022 走看看