jvm常量池

常量池:    就是一张常量表,虚拟机指令根据常量表找到要执行的类名,方法名,参数类型,字面量等信息
    可以提高程序的性能和内存效率,避免重复创建相同内容的对象


    一个类运行,要先编译成字节码

    字节码组成:    类基本信息,常量池,类方法定义(包含 虚拟机指令)

        可以用javap反编译字节码文件
        javap -v HelloWorld.class

常量池有四种类型


静态常量池:    静态常量池是.class文件中的,包含了编译期生成的各种字面量和符号引用,
        如字符串、数字、类名、方法名等。静态常量池在编译时就被确定,不会在运行时改变。

    
运行时常量池:        是存在.class文件中的,是每个类或接口的静态常量池在运行时的表现形式
            当类被加载,它的常量池信息会被放入运行时常量池,
            运行时也可以动态添加新的常量(如String类的intern()方法)
            并把里面的符号地址变为真实地址
    
    常量池中信息被加载到运行时常量池中,此时,信息还没有成为java中的字符串对象
    只有在调用这个字符串变量的时候,才会将信息变成对象      //懒惰
    创建对象时,先在 串池StringTable 中查找,
    如果没有在串池中创建新的,如果有使用串池中对象
    串池是HashTable哈希表结构的

        
    String s1="a";
    String s2="b";
    STring s3="ab";
    String s4=s1+s2;    
        //此处调用了s1和s2,先查找串池,串池中没有,在串池中创建a和b
        //然后底层对字符串变量相加做了优化,用了StringBuilder,和append方法
        //然后new了一个新字符串
        //但是new的对象都是存在堆中的
    sout(s3==s4);    //false
        //这里调用了s3,在串池中创建ab
        //但是s4是在堆中,s3在串池,不是一个对象,所以是false


    String s5="a"+"b";    
        //javac优化:编译期直接将常量"a"和"b"相加得到ab,不用StringBuilder运行时处理
    sout(s3==s5);    //true
        //这里调用了s3和s5,s3先在串池中查找,存在ab,所以就直接调用
        //再调用s5,再在串池中查找,同样找到了,所以是串池的同一个对象
        //返回true
                
    
        原因:    s1和s2是变量,在运行时引用的值可能被修改,结果不确定,必须在运行期间处理成ab
            而"a","b"是常量,javac在编译期间优化,结果已经在编译期间确定为ab,无法改变

        总结:    字符串变量只有在调用时,才会被创建,而且java底层对字符串加法做了优化,使用            StringBuilder操作,最终获取的方式是使用new的方式获取,存放在堆中

            字符串常量的计算,会直接在编译时期获得结果,然后直接在串池中寻找
        


串池:        数据结构:    哈希表=数组+链表

        特性:    常量池中字符串只是符号,第一次用到时才会变成对象
            利用串池的机制,避免重复创建字符串对象
            字符串变量拼接的原理是StringBuilder
            字符串常量拼接的原理是编译期优化
        jdk8:    可以用intern方法,指定将串池中还没有的字符串对象放入串池,并返回该对象
        jdk6:    如果串池中没有,就会复制对象,并放入串池.如果有就不放如串池

    串池的位置:    1.6:    串池在常量池中
            1.8后:    串池到了堆中
            原因:    永久代的内存回收效率低,只有等待老年代的空间不足时才会触发
            
        GCOverheadLimitError:    %98的时间用于垃圾回收,但是只回收2%空间,就会抛出异常


    垃圾回收:    当内存不足时,没有被引用的字符串常量会被垃圾回收
            

    性能调优:    串池是哈希表结构,哈希表越大,里面buckets桶的个数越多,
                哈希碰撞的概率越小,查询速度越快
                -XX:StringTable=1009    (1009是串池桶最小值)
        
            考虑将大量且重复字符串对象入池,用intern方法入池,来减少内存占用

包装类的常量池:
        包装类的常量池是存在于堆中的,是一种缓存技术,用于存储包装类对象,
        如Integer、Long、Character等。
        包装类的常量池可以实现包装类对象共享,提高性能。
        包装类的常量池只缓存了一定范围内的值,超出范围的值会创建新的对象。    


 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值