Java8 String内存优化之字符串常量池

前言

工作中遇到一个场景,需要在本地缓存大量信息,上百万数量级,耗费了大量内存4~5G,调研发现其大部分是String类型文本,因机器内存有限,故希望减少该内存占用,从String字段入手。
本文章是实验不同情况下String占用内存的表现。

环境

mac os 10.12.6
java version “1.8.0_112”
Java™ SE Runtime Environment (build 1.8.0_112-b16)
Java HotSpot™ 64-Bit Server VM (build 25.112-b16, mixed mode)
IntelliJ idea
G1垃圾回收器

实验思路

结合网上的一些查询,Java 8中字符串已经放到堆上存储,故没有大小限制;另外如果内存不足时会GC释放掉不再使用的字符串内存,故设计实验如下:

编号 名称 目的
1 存放近1G的字符串内存 作为2对照实验
2 存放近1G的字符串内存-存入字符串常量池 证明字符串内存在堆上,无大小限制
3 存放近1G的字符串内存-相同字符 作为4对照实验
4 存放近1G的字符串内存-相同字符-字符串常量池 证明字符串常量池可复用内存
5 存放超过jvm内存的字符串内存-字符串常量池 作为6对照实验
6 存放超过jvm内存的字符串内存-字符串常量池-释放内存 证明字符串常量池可被释放

实验1和实验2-字符串内存无大小限制

实验1-存放近1G的字符串内存

public static void main(String[] args) throws InterruptedException {
   
        System.out.println("--begin...");
        String[] result = test1_1();
        System.out.println("--end");
        System.out.println("--gc...");
        System.gc();
        System.out.println("--gc end");
    }

    private static String[] test1_1() {
   
        //jvm:-Xmx1G -XX:+PrintGCDetails -XX:+UseG1GC
        String[] array = new String[35 * 1024 * 1024];
        //37335040(3700万)次循环
        for (int i = 0; i < 35 * 1024 * 1024; i++) {
   
            String str1 = new String("A");
            array[i] = str1;
            if (i % 1024 * 1024 == 0) {
   
                System.out.println("now i=" + i);
            }
        }
        return array;
    }

最后输出:

now i=36696064
now i=36697088
now i=36698112
now i=36699136
–end
–gc…
[Full GC (System.gc()) 1005M->980M(1024M), 3.8400925 secs]
[Eden: 3072.0K(44.0M)->0.0B(51.0M) Survivors: 7168.0K->0.0B Heap: 1005.5M(1024.0M)->980.4M(1024.0M)], [Metaspace: 3345K->3345K(1056768K)]
[Times: user=5.63 sys=0.23, real=3.84 secs]
[GC concurrent-mark-abort]
–gc end
Heap
garbage-first heap total 1048576K, used 1003938K [0x0000000780000000, 0x0000000780102000, 0x00000007c0000000)
region size 1024K, 1 young (1024K), 0 survivors (0K)
Metaspace used 3351K, capacity 4564K, committed 4864K, reserved 1056768K
class space used 369K, capacity 388K, committed 512K, reserved 1048576K

实验2-存放近1G的字符串内存-存入字符串常量池

String.intern()方法可以从字符串常量池中获取,如不存在则会添加到字符串常量池中,所以本实验使用该方法:

public static void main(String[] args) throws InterruptedException {
   
        System.out.println("--begin...");
        String[] result = test1_1();
        System.out.println("--end");
        System.out.println("--gc...");
        System.gc();
        System.out.println("--gc end");
    }

    private static String[] test1_1() {
   
        //jvm:-Xmx1G -XX:+PrintGCDetails -XX:+UseG1GC
        String[] array = new String[35 * 1024 * 1024];
        //37335040(3700万)次循环
        for (int i 
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值