阅读 68

JVM中常量池和String的常量池

前言

  • 在JVM模型中专门有常量池的讲解,为什么需要常量池呢?就像我们平时生活中总是需要一些标签的,常量的坐拥就是固定不变的变量。方便我们以此为标杆

问题描述

  • 上面也说了new String 是不断的开辟空间来存储内容的。但是String使用特别广泛这样操作的话很容易造成OOM

public static void main(String[] args) throws InterruptedException {
    List<String> list = new ArrayList<>();

    for (int i = 0; i < 200000; i++) {
        String text = new String("abcsdlkfjsldkfjsalkdjflkasjdflaksjdfl;kasdjgl;kasjgasldk;djgsadlkjgsadlkdjgfas;lkdfjsaf");
        list.add(text);
    }
    System.out.println(list.size());
}复制代码
  • 上面的程序是不断的创建一个字符串然后加入到集合中。如果你想更容易出现OOM现象你可以将字符串调的更大点循环加的更大点。

  • 除了此外我们还需要通过idea调整程序的最大堆内存 。

image-20210514103249065

  • 然后我们启动程序,不出意外就会出现OOM 。 而下面的错误是GC次数超出了限制了。

  • 这里我们这样理解GC说明堆中对象太多了。而GC太频繁是因为内存使用很多而且是使用的对象。所以每次GC但是删不掉任何对象

  • 这也侧面反映了new的弊端

image-20210514103319962

解析

  • 因为我们不停的new对象到堆中。堆中的空间又是有效的肯定会出现问题。你可能会说我的堆空间很大吃得消这些空间

  • 但是如果我的程序死循环了一直new对象呢。其实我们仔细分析下我们上面的代码。我们是不断的new相同内容在堆中。就好像你一直在写nihao在不同的纸上

  • 就算你写了100张纸。那么这样的意义又在哪里呢。所以java为我们提供了常量池。常量池就是专门存储string中内容的。因为我们的String大多数内容都会重复

优化

  • 下面我们将代码中new String的方式改用双引号。再运行程序看看结果

public static void main(String[] args) throws InterruptedException {
    List<String> list = new ArrayList<>();

    for (int i = 0; i < 200000; i++) {
        String text =  "abcsdlkfjsldkfjsalkdjflkasjdflaksjdfl;kasdjgl;kasjgasldk;djgsadlkjgsadlkdjgfas;lkdfjsaf";
        list.add(text);
    }
    System.out.println(list.size());
}复制代码
  • 此时程序就会执行成功。如果你借助其他类似visualvm工具就能够看到内存的使用情况了

总结

  • 虽然我们使用双引号来实现字符串的构建。但是我们要知道构建出来的字符串都存在在JVM中的位置。这样就会避免掉值判断相等的问题了


作者:本该努力的年龄千万别放弃
链接:https://juejin.cn/post/7026319761567514660


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐