Java内存使用量测试 看看我们天天在用的JVM到底浪费了多少内存资源

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java内存使用量测试 看看我们天天在用的JVM到底浪费了多少内存资源相关的知识,希望对你有一定的参考价值。

JVM内存使用量测试
测试各种不同的数据结构在JVM中的内存使用量

  1 import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
  2 
  3 import java.lang.management.ManagementFactory;
  4 import java.lang.management.MemoryMXBean;
  5 import java.lang.management.MemoryUsage;
  6 import java.util.HashSet;
  7 import java.util.Map;
  8 import java.util.Set;
  9 
 10 /** JVM内存使用量测试
 11  * 测试各种不同的数据结构在JVM中的内存使用量
 12  */
 13 public class MemUsageTest
 14 {
 15     static final long KILO = 1024L;
 16     static final long MEGA = KILO * KILO;
 17 
 18     static double divide(long a, long b) {
 19         return ((double)a)/b;
 20     }
 21     static StringBuilder sbMem = new StringBuilder(16);
 22     static String memStr(long mem) {
 23         return memStr(mem, null);
 24     }
 25     static String memStr(long mem, String msg) {
 26         sbMem.setLength(0);
 27         if(msg==null || msg.length()==0){
 28             
 29         }else{
 30             sbMem.append(msg).append(": ");
 31         }
 32         
 33         if(mem == 0){
 34             sbMem.append("0");
 35             return sbMem.toString();
 36         }
 37         
 38         if(mem < 0){
 39             sbMem.append("- ");
 40             mem = -mem;
 41         }
 42         if(mem >= MEGA){
 43             sbMem.append(mem / MEGA);
 44             sbMem.append("M ");
 45             mem %= MEGA;
 46         }
 47         if(mem >= KILO){
 48             sbMem.append(mem / KILO);
 49             sbMem.append("K ");
 50             mem %= KILO;
 51         }
 52         if(mem > 0){
 53             sbMem.append(mem);
 54             sbMem.append("B");
 55         }
 56         return sbMem.toString();
 57     }
 58 
 59     static final Runtime RUNTIME = Runtime.getRuntime();
 60     static final MemoryMXBean MEM_MXBEAN = ManagementFactory.getMemoryMXBean();
 61     static long LAST_MEM = 0;
 62     public static void printMemUsage() {
 63         printMemUsage(null);
 64     }
 65     public static void printMemUsage(String msg) {
 66         if(msg==null || msg.length()==0){
 67             System.out.println("==================== MemUsage ====================");
 68         }else{
 69             System.out.println("==================== MemUsage ("+msg+") ====================");
 70         }
 71         System.gc();
 72         
 73         /*System.out.println(divide(RUNTIME.totalMemory()-RUNTIME.freeMemory(), MEGA));//usage.getUsed()
 74         System.out.println(divide(RUNTIME.totalMemory(), MEGA));//usage.getCommitted()
 75 */        //System.out.println(divide(RUNTIME.maxMemory(), MEGA));//usage.getMax()
 76         
 77         MemoryUsage usage = MEM_MXBEAN.getHeapMemoryUsage();
 78         //usage = MEM_MXBEAN.getNonHeapMemoryUsage();
 79         //System.out.println(memStr(usage.getInit()));
 80         System.out.println(memStr(usage.getUsed(), "使用量       "));//使用量
 81         System.out.println(memStr(usage.getUsed()-LAST_MEM, "使用量增量"));//使用量增量
 82         System.out.println(memStr(usage.getCommitted(), "提交总量   "));//提交总量
 83         //System.out.println(memStr(usage.getMax()));
 84         
 85         //if(LAST_MEM <= 0){
 86             LAST_MEM = usage.getUsed();
 87         //}
 88     }
 89     
 90     public static int same(int i){
 91         return i;
 92     }
 93     public static Object same(Object i){
 94         return i;
 95     }
 96 
 97     static String[] strs;
 98     static Object[] objs;
 99     static int[] ints;
100     static Integer[] integers;
101     static Set<Integer> integerSet;
102     public static void main( String[] args )
103     {
104         printMemUsage();
105 
106         //String[]
107         //每个对象平均占用60B
108         strs = new String[(int) MEGA];
109         printMemUsage("String[]");
110 
111         int i;
112         for(i=0;i<strs.length;i++){
113             //strs[i] = "";
114             //strs[i] = new String("");
115             strs[i] = String.format("%08d", i);
116             //strs[i] = String.valueOf(Math.random());
117         }
118         printMemUsage();
119         
120         strs = null;
121         printMemUsage();
122 
123         //Object[]
124         //每个对象平均占用20B
125         objs = new Object[(int) MEGA];
126         printMemUsage("Object[]");
127         
128         for(i=0;i<objs.length;i++){
129             objs[i] = new Object();
130         }
131         printMemUsage();
132         
133         objs = null;
134         printMemUsage();
135 
136         //int[]
137         //每个对象平均占用4B
138         ints = new int[(int) MEGA];
139         printMemUsage("int[]");
140         
141         for(i=0;i<ints.length;i++){
142             ints[i] = same(i);
143         }
144         printMemUsage();
145         
146         ints = null;
147         printMemUsage();
148 
149         //Integer[]
150         //每个对象平均占用20B
151         integers = new Integer[(int) MEGA];
152         printMemUsage("Integer[]");
153         
154         for(i=0;i<integers.length;i++){
155             integers[i] = i;
156         }
157         printMemUsage();
158         
159         integers = null;
160         printMemUsage();
161 
162         //HashSet<Integer>
163         //每个对象平均占用56B
164         integerSet = new HashSet<Integer>(1000000);
165         printMemUsage("HashSet<Integer>");
166         
167         for(i=0;i<MEGA;i++){
168             integerSet.add(i);
169         }
170         printMemUsage();
171         
172         integerSet = null;
173         printMemUsage();
174 
175         //fastutil.IntOpenHashSet
176         //每个对象平均占用8B
177         integerSet = new IntOpenHashSet(1000000);
178         printMemUsage("fastutil.IntOpenHashSet");
179         
180         for(i=0;i<MEGA;i++){
181             ((IntOpenHashSet)integerSet).add(i);
182         }
183         printMemUsage();
184         
185         integerSet = null;
186         printMemUsage();
187     }
188 }

 

运行结果如下,由此可见JVM对String、Object、封装类型(如Integer)等的存储均有较大的消耗。

使用fastutil的集合类,可以比Java系统集合类节省不少的内存空间,因为HashMap、HashSet等类不仅不支持直接存放原始类型int,而且还要把存储的对象封装成Node(哈希桶链表的节点),这里消耗的内存空间比fastutil多出了7倍之多!

==================== MemUsage ====================
使用量       : 1M 187K 384B
使用量增量: 1M 187K 384B
提交总量   : 123M 
==================== MemUsage (String[]) ====================
使用量       : 4M 546K 128B
使用量增量: 3M 358K 768B
提交总量   : 123M 
==================== MemUsage ====================
使用量       : 60M 730K 728B
使用量增量: 56M 184K 600B
提交总量   : 622M 512K 
==================== MemUsage ====================
使用量       : 730K 712B
使用量增量: - 60M 16B
提交总量   : 632M 512K 
==================== MemUsage (Object[]) ====================
使用量       : 4M 730K 728B
使用量增量: 4M 16B
提交总量   : 606M 
==================== MemUsage ====================
使用量       : 20M 730K 728B
使用量增量: 16M 
提交总量   : 631M 
==================== MemUsage ====================
使用量       : 730K 712B
使用量增量: - 20M 16B
提交总量   : 631M 512K 
==================== MemUsage (int[]) ====================
使用量       : 4M 730K 728B
使用量增量: 4M 16B
提交总量   : 629M 512K 
==================== MemUsage ====================
使用量       : 4M 730K 728B
使用量增量: 0
提交总量   : 602M 
==================== MemUsage ====================
使用量       : 730K 712B
使用量增量: - 4M 16B
提交总量   : 629M 
==================== MemUsage (Integer[]) ====================
使用量       : 4M 730K 728B
使用量增量: 4M 16B
提交总量   : 606M 
==================== MemUsage ====================
使用量       : 20M 728K 728B
使用量增量: 15M 1022K 
提交总量   : 625M 512K 
==================== MemUsage ====================
使用量       : 730K 712B
使用量增量: - 19M 1022K 16B
提交总量   : 627M 512K 
==================== MemUsage (HashSet<Integer>) ====================
使用量       : 730K 952B
使用量增量: 240B
提交总量   : 627M 512K 
==================== MemUsage ====================
使用量       : 56M 729K 368B
使用量增量: 55M 1022K 440B
提交总量   : 628M 
==================== MemUsage ====================
使用量       : 731K 288B
使用量增量: - 55M 1022K 80B
提交总量   : 642M 
==================== MemUsage (fastutil.IntOpenHashSet) ====================
使用量       : 8M 795K 288B
使用量增量: 8M 64K 
提交总量   : 610M 
==================== MemUsage ====================
使用量       : 8M 751K 152B
使用量增量: - 44K 136B
提交总量   : 638M 
==================== MemUsage ====================
使用量       : 751K 88B
使用量增量: - 8M 64B
提交总量   : 602M 

 


以上是关于Java内存使用量测试 看看我们天天在用的JVM到底浪费了多少内存资源的主要内容,如果未能解决你的问题,请参考以下文章

JVM那些事儿之内存区域

深入JVM垃圾回收机制,值得你收藏

Java虚拟机(JVM)-- 堆内存调优

JVM虚拟机-03JVM内存分配机制与垃圾回收算法

性能测试三十四:jvm内存结构(栈堆永久代)

JVM内存结构和垃圾回收