V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
pkwenda
V2EX  ›  Java

问个 jvm 拼接字符串, heap oom 的问题

  •  
  •   pkwenda ·
    pkwenda · 2021-01-05 02:15:51 +08:00 · 750 次点击
    这是一个创建于 1214 天前的主题,其中的信息可能已经有所发展或是发生改变。

    很简单的一段代码 1:

    
    	public static void main(String[] args) {
    		int i = 0;
    		String a = "hello";
    		try {
    			while (true) {
    				a = a + " world";
    				i++;
    				System.out.println(i);
    			}
    		} catch (Throwable e){
    			System.out.println(e);  
    			System.out.println(i);  
    			System.out.println(a);
    		}
    	}
    
    

    很简单的一段代码 2:

    public static void main(String[] args) {
    		int i = 0;
    		String a = "hello";
    		try {
    			while (true) {
    				a = a + a;
    				i++;
    				System.out.println(i);
    			}
    		} catch (Throwable e){
    			System.out.println(e); 
    			System.out.println(i);  
    			System.out.println(a);
    		}
    	}
    
    

    设置 1M

    -Xmx1m -XX:+PrintGCDetails
    

    反汇编结果:

    image.png

    结果

    • 代码 1 拼接字符串,从常量池到栈顶,循环 几十万次,终于 heap oom 空间不足

    • 代码 2 加载栈帧中的本地变量表 a 变量:17 次 oom,加大内存 10m -- 19 次后 oom,加到 100m -- 22 次后 oom

    我不理解为什么 代码 2,我不断的加大内存,循环次数远没有达到我预期?按我的期望值,heap 空间足够 new 非常多的对象,为什么?

    17
    18
    [GC (Allocation Failure) [PSYoungGen: 23074K->3152K(29696K)] 23074K->8280K(98304K), 0.0038643 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
    19
    [GC (Allocation Failure) [PSYoungGen: 24127K->544K(29696K)] 29255K->21032K(98304K), 0.0070954 secs] [Times: user=0.02 sys=0.01, real=0.00 secs] 
    20
    21
    [Full GC (Ergonomics) [PSYoungGen: 22036K->0K(29696K)] [ParOldGen: 61448K->20931K(67584K)] 83484K->20931K(97280K), [Metaspace: 3312K->3312K(1056768K)], 0.0053285 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
    [Full GC (Ergonomics) [PSYoungGen: 20480K->0K(29696K)] [ParOldGen: 61891K->61891K(68608K)] 82371K->61891K(98304K), [Metaspace: 3312K->3312K(1056768K)], 0.0065019 secs] [Times: user=0.03 sys=0.01, real=0.00 secs] 
    [GC (Allocation Failure) [PSYoungGen: 0K->0K(29696K)] 61891K->61891K(98304K), 0.0007047 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    [Full GC (Allocation Failure) [PSYoungGen: 0K->0K(29696K)] [ParOldGen: 61891K->61873K(68608K)] 61891K->61873K(98304K), [Metaspace: 3312K->3312K(1056768K)], 0.0063003 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
    java.lang.OutOfMemoryError: Java heap space
    21
    Heap
     PSYoungGen      total 29696K, used 761K [0x00000007bdf00000, 0x00000007c0000000, 0x00000007c0000000)
      eden space 25600K, 2% used [0x00000007bdf00000,0x00000007bdfbe428,0x00000007bf800000)
      from space 4096K, 0% used [0x00000007bf800000,0x00000007bf800000,0x00000007bfc00000)
      to   space 4096K, 0% used [0x00000007bfc00000,0x00000007bfc00000,0x00000007c0000000)
     ParOldGen       total 68608K, used 61873K [0x00000007b9c00000, 0x00000007bdf00000, 0x00000007bdf00000)
      object space 68608K, 90% used [0x00000007b9c00000,0x00000007bd86c5c8,0x00000007bdf00000)
     Metaspace       used 3319K, capacity 4496K, committed 4864K, reserved 1056768K
      class space    used 372K, capacity 388K, committed 512K, reserved 1048576K
    
    
    

    内存瞬间被吃了很大一块

    pkwenda
        1
    pkwenda  
    OP
       2021-01-05 02:24:50 +08:00
    我好像看明白了,内存是呈几何倍增长的,我写的是 a + a .... 懂了,果然还得是小黄鸭 debug 法
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   773 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 20:25 · PVG 04:25 · LAX 13:25 · JFK 16:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.