zoukankan      html  css  js  c++  java
  • JVM笔记3-java内存区域之运行时常量池

    1.运行时常量池属于线程共享区中的方法区。

    2.运行时常量池用于编译期生成的各种自变量,符号引用,这部分内用将在类加载后接入方法区的运行时常量池中存放。

    看如下代码所示,如图:

    public class Test {
        public static void main(String[] args) {
            String s1 = "abc";
            String s2 = "abc";
    
            String s3 = new String("abc");
            System.out.println(s1 == s2);
            System.out.println(s1 == s3);
        }
    }

    很明显s1 == s2为true,而s1 == s3为false。

    因为基本数据类型和抽象数据类的引用是放在栈帧的局部变量表中。所以s1 s2是放在栈帧的局部变量表中。而“abc”这个对象则是放在运行时常量池中。

    而这个常量池有钟数据结构叫Stringtable,它的数据类型可以理解为HashSet。而HashSet是无序的,不可重复的。因此第一次将定义的“abc"放入其中

    而第二次定义中发现常量池中有“abc”了,则不再创建“abc"了,此时s1 和s2则引用的是同一个”abc“。因此s1 == s2为true。

    而s3则是通过new出来的实例,则放进java堆中,此时s3引用的是堆中的”abc"。因此s1 == s3为false。

    如果将s3变动一下又会产生什么结果呢?如下代码所示:

    public class Test {
        public static void main(String[] args) {
            String s1 = "abc";
            String s2 = "abc";
    
            String s3 = new String("abc");
            System.out.println(s1 == s2);
            System.out.println(s1 == s3);
            System.out.println(s1 == s3.intern());
        }
    }

    很明显System.out.println(s1 == s3.intern());为true。因为s3.intern()是将堆中的“abc"拿出来放进常量池中,而常量池中已经存在”abc“,因此直接把常量池中的

    ”abc"引用给了s3,因此System.out.println(s1 == s3.intern());为true,这就形成了运行时常量。

    注意当常量池中满了同样会抛出OutOfMemory内存溢出异常。

    这里顺便提提一个叫做直接内存

    直接内存:并不是虚拟机运行时数据区的的一部分。当然了,这也不是虚拟机规范中定义的内存 区域。而是一种对外的内存区域。

    NIO正是经常用到了对外内存。同样当对外内存满了也照样会抛出OutOfMemory内存溢出异常。抛出这种异常也要考虑一下这个区域。

  • 相关阅读:
    C# 使用DateTime.TryParseExact将自定义日期类型转换成日期
    ASP.NET WebServices 因 URL 意外地以“/HelloWorld”结束,请求格式无法识别。
    [UE4]计算2点坐标附近的坐标:线性插值法
    [UE4]Selector和Sequence的区别
    [UE4]蒙太奇动画运行时不播放,预览是好的
    [UE4]蓝图函数库小结
    [UE4]C++调用蓝图函数:BlueprintImplementableEvent函数说明符用法
    [UE4GamePlay架构(九)GameInstance(转)
    [UE4]C++取得蓝图控件实例
    [UE4]虚幻4的智能指针
  • 原文地址:https://www.cnblogs.com/huangjuncong/p/8451310.html
Copyright © 2011-2022 走看看