运行时堆内存的使用

Posted 点滴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了运行时堆内存的使用相关的知识,希望对你有一定的参考价值。

 1 /**
 2  * Created by wb-xxd249566 on 2017/4/1.
 3  * -Xmx20m -Xms5m -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseSerialGC
 4  */
 5 public class HeapAlloc {
 6 
 7     public static void main(String[] args){
 8         printMemoryStatus();
 9         alloc(1);
10         printMemoryStatus();
11         alloc(4);
12         printMemoryStatus();
13     }
14 
15     public static void printMemoryStatus(){
16         System.out.println("Max Memory="+Runtime.getRuntime().maxMemory()+"bytes");
17         System.out.println("Free Memory="+Runtime.getRuntime().freeMemory()+"bytes");
18         System.out.println("Total Memory="+Runtime.getRuntime().totalMemory()+"bytes");
19     }
20 
21     public static void alloc(int size){
22         byte[] b = new byte[size*1024*1024];
23         System.out.println("Alloc "+size+"M Space");
24         System.out.println("=========================================================");
25     }
26 }
126248424-125199832=1048592≈1024*1024
125199832-121005512=4194320≈4*1024*1024
TotalMemory表示当前总内存,当前总内存总是在-Xms和-Xmx之间,从-Xms开始根据需求向上增长
FreeMemory表示当前空闲内存,空闲内存应该是当前总内存减去当前已经使用的空间
但这样理解并不全面:
--------------------------------------------------------------------------------------------------------------------------
Xmx20m -Xms5m -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseSerialGC
--------------------------------------------------------------------------------------------------------------------------

-XX:InitialHeapSize=5242880 -XX:MaxHeapSize=20971520 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseSerialGC 
 
5242880 = 5*1024*1024            对应-Xms5m
 
20971520 = 20 * 1024 * 1024    对应-Xmx20m
 
Max Memory=20316160bytes    实际最大堆内存小于最大堆内存 20971520-20316160=655360
                                                     655360/1024/1024=0.625(M)
这是因为分配给堆的内存空间和实际可用的内存空间并非一个概念。由于垃圾回收的需要,虚拟机会对堆空间进行分区管理,不同的区域采用不通的回收算法,一些算法会使用空间换时间的策略工作,因此会存在可用内存的损失。
最终的结果就是实际可用内存会浪费大小等于from/to的空间。
这里from/to空间各为192k,即192*1024*2=393216≠655360
发现仍然有偏差,这个偏差是由于虚拟机内部并没有直接使用新生代from/to的大小,而是进一步对它们做了对齐操作。
 
[0x00000000fec00000, 0x00000000fee10000, 0x00000000ff2a0000)
    下界                                当前上界                            上界
上界 - 下界 = eden + from + to 
0x00000000ff2a0000 - 0x00000000fec00000 = 0x6A0000 = 6946816(d)
gen_size = 6946816 (即新生代大小)
SurvivorRatio =8 (幸存代比例,默认为8)
size=gen_size/(SurvivorRatio + 2) 
compute_survivor_size = (size)&~((alignment) - 1 ) = 694681 &~ ((2^16)-1)
                                       = 0xA9999 & 0xFFFFFFFFFFFFE0000 = 0xA0000
                                       = 655360
计算后,from/to区间大小为655360,与实际输出值吻合。
 
Free Memory=4972032bytes
Total Memory=6094848bytes
[GC (Allocation Failure) [DefNew: 1096K->192K(1856K), 0.0016378 secs] 1096K->620K(5952K), 0.0016618 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Alloc 1M Space
=========================================================================
Max Memory=20316160bytes
Free Memory=4360848bytes
Total Memory=6094848bytes
[GC (Allocation Failure) [DefNew: 1264K->0K(1856K), 0.0008827 secs][Tenured: 1644K->1645K(4096K), 0.0016291 secs] 1693K->1645K(5952K), [Metaspace: 3220K->3220K(1056768K)], 0.0025429 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Alloc 4M Space
=========================================================================
Max Memory=20316160bytes
Free Memory=4434096bytes
Total Memory=10358784bytes
Heap
 def new generation   total 1920K, used 73K [0x00000000fec00000, 0x00000000fee10000, 0x00000000ff2a0000)
[0x00000000fec00000, 0x00000000fee10000, 0x00000000ff2a0000)
    下界                                当前上界                            上界
上界 - 下界 = eden + from + to 
0x00000000ff2a0000 - 0x00000000fec00000 = 0x6A0000 = 6946816(d)
  eden space 1728K,   4% used [0x00000000fec00000, 0x00000000fec12688, 0x00000000fedb0000)
  from space 192K,   0% used [0x00000000fedb0000, 0x00000000fedb0000, 0x00000000fede0000)
  to   space 192K,   0% used [0x00000000fede0000, 0x00000000fede0000, 0x00000000fee10000)
 tenured generation   total 8196K, used 5741K [0x00000000ff2a0000, 0x00000000ffaa1000, 0x0000000100000000)
   the space 8196K,  70% used [0x00000000ff2a0000, 0x00000000ff83b4b8, 0x00000000ff83b600, 0x00000000ffaa1000)
 Metaspace       used 3338K, capacity 4494K, committed 4864K, reserved 1056768K
  class space    used 373K, capacity 386K, committed 512K, reserved 1048576K
 
Process finished with exit code 0
 

以上是关于运行时堆内存的使用的主要内容,如果未能解决你的问题,请参考以下文章

JVM 运行时堆内存如何分代?

在方法中使用实例变量时堆和堆栈(Java内存)

为啥重新启动活动时堆内存会增加?

从工厂函数返回右值引用时堆/内存损坏

执行 <jdbc:initialize-database> 时堆内存不足

删除数组指针C++时堆损坏