现在的位置: 首页 > 程序设计> 正文
Java开发内存占用监测
2013年08月05日 程序设计 暂无评论 ⁄ 被围观 4,307+

在开发Java的过程中,怎么样来监测一个对象占用的内存大小,对于调试程序,优化程序来说,有很大的帮助,本文介绍了一个开发包,JAMM (Java Agent for Memory Measurements),可以很方便的在程序的运行过程中动态监测对象的内存占用情况。
This short article shows how to measure java object memory size at runtime with JAMM, a java agent dedicated to measure actual object memory use including JVM overhead.
JAMM uses the Instrumentation implementation provided by the JVM to compute memory usage of a given object by calling the getObjectSize(..) method.

It is quite simple to use, as explained by the author:

1
2
3
4
5
        
MemoryMeter meter = new MemoryMeter();
meter.measure(object);
meter.measureDeep(object);
meter.countChildren(object);
        
MemoryMeter meter = new MemoryMeter();
meter.measure(object);
meter.measureDeep(object);
meter.countChildren(object);
The only constraint is to attach JAMM java agent to the JVM before using it to measure memory usage, by starting the JVM with the -javaagent option pointing to the JAMM jar.
So, we are going to write a JUnit that shows how to use JAMM, but before we need to setup maven to achieve this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
        
< dependencies > 
      < dependency > 
          < groupid >junit</ groupid > 
          < artifactid >junit</ artifactid > 
          < version >4.11</ version > 
          < scope >test</ scope > 
      </ dependency > 
 
      <!-- jamm java agent --> 
      < dependency > 
          < groupid >com.github.stephenc</ groupid > 
          < artifactid >jamm</ artifactid > 
          < version >0.2.5</ version > 
          < scope >test</ scope > 
      </ dependency > 
 
 </ dependencies > 
 
 < build > 
      < plugins > 
 
          <!-- copies java agent dependency into the target directory --> 
          < plugin > 
              < groupid >org.apache.maven.plugins</ groupid > 
              < artifactid >maven-dependency-plugin</ artifactid > 
              < version >2.8</ version > 
              < executions > 
                  < execution > 
                      < id >copy-dependencies</ id > 
                      < phase >generate-test-resources</ phase > 
                      < goals > 
                          < goal >copy</ goal > 
                      </ goals > 
                      < configuration > 
                          < artifactitems > 
                              < artifactitem > 
                                  < groupid >com.github.stephenc</ groupid > 
                                  < artifactid >jamm</ artifactid > 
                                  < version >0.2.5</ version > 
                                  < type >jar</ type > 
                                  < outputdirectory >${project.build.directory}</ outputdirectory > 
                                  < destfilename >jamm.jar</ destfilename > 
                              </ artifactitem > 
                          </ artifactitems > 
                      </ configuration > 
                  </ execution > 
              </ executions > 
          </ plugin > 
 
          <!-- executes test with java agent options of the JVM --> 
          < plugin > 
              < groupid >org.apache.maven.plugins</ groupid > 
              < artifactid >maven-surefire-plugin</ artifactid > 
              < version >2.14</ version > 
              < configuration > 
                  < argline >-javaagent:${project.build.directory}/jamm.jar</ argline > 
              </ configuration > 
          </ plugin > 
 
      </ plugins > 
 </ build >
        
< dependencies > 
      < dependency > 
          < groupid >junit</ groupid > 
          < artifactid >junit</ artifactid > 
          < version >4.11</ version > 
          < scope >test</ scope > 
      </ dependency > 

      <!-- jamm java agent --> 
      < dependency > 
          < groupid >com.github.stephenc</ groupid > 
          < artifactid >jamm</ artifactid > 
          < version >0.2.5</ version > 
          < scope >test</ scope > 
      </ dependency > 

 </ dependencies > 

 < build > 
      < plugins > 

          <!-- copies java agent dependency into the target directory --> 
          < plugin > 
              < groupid >org.apache.maven.plugins</ groupid > 
              < artifactid >maven-dependency-plugin</ artifactid > 
              < version >2.8</ version > 
              < executions > 
                  < execution > 
                      < id >copy-dependencies</ id > 
                      < phase >generate-test-resources</ phase > 
                      < goals > 
                          < goal >copy</ goal > 
                      </ goals > 
                      < configuration > 
                          < artifactitems > 
                              < artifactitem > 
                                  < groupid >com.github.stephenc</ groupid > 
                                  < artifactid >jamm</ artifactid > 
                                  < version >0.2.5</ version > 
                                  < type >jar</ type > 
                                  < outputdirectory >${project.build.directory}</ outputdirectory > 
                                  < destfilename >jamm.jar</ destfilename > 
                              </ artifactitem > 
                          </ artifactitems > 
                      </ configuration > 
                  </ execution > 
              </ executions > 
          </ plugin > 

          <!-- executes test with java agent options of the JVM --> 
          < plugin > 
              < groupid >org.apache.maven.plugins</ groupid > 
              < artifactid >maven-surefire-plugin</ artifactid > 
              < version >2.14</ version > 
              < configuration > 
                  < argline >-javaagent:${project.build.directory}/jamm.jar</ argline > 
              </ configuration > 
          </ plugin > 

      </ plugins > 
 </ build >

Next, write the following JUnit that explores the JAMM features:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
 package org.javabenchmark.memory; 
 
 import java.util.ArrayList; 
 import java.util.List; 
 import org.github.jamm.MemoryMeter; 
 import org.junit.Test; 
 
 public class MemoryMeterTest { 
 
      private MemoryMeter meter = new MemoryMeter(); 
 
      @Test 
      public void shouldMeasureMemoryUsage() { 
 
          String st1 = "This is the string #1" ; 
          measure(st1); 
 
          String st2 = "This is the string #2 and it has more chars." ; 
          measure(st2); 
 
          List aList = new ArrayList( 0 ); 
          measure(aList); 
 
          aList.add(st1); 
          measure(aList); 
 
          aList.add(st2); 
          measure(aList); 
      } 
 
      private void measure(Object anObject) { 
          System.out.println( "-----------------------------------" ); 
          System.out.printf( "size: %d bytes\n" , meter.measure(anObject)); 
          System.out.printf( "retained size: %d bytes\n" , meter.measureDeep(anObject)); 
          System.out.printf( "inner object count: %d\n" , meter.countChildren(anObject)); 
      } 
 }
 package org.javabenchmark.memory; 

 import java.util.ArrayList; 
 import java.util.List; 
 import org.github.jamm.MemoryMeter; 
 import org.junit.Test; 

 public class MemoryMeterTest { 

      private MemoryMeter meter = new MemoryMeter(); 

      @Test 
      public void shouldMeasureMemoryUsage() { 

          String st1 = "This is the string #1" ; 
          measure(st1); 

          String st2 = "This is the string #2 and it has more chars." ; 
          measure(st2); 

          List aList = new ArrayList( 0 ); 
          measure(aList); 

          aList.add(st1); 
          measure(aList); 

          aList.add(st2); 
          measure(aList); 
      } 

      private void measure(Object anObject) { 
          System.out.println( "-----------------------------------" ); 
          System.out.printf( "size: %d bytes\n" , meter.measure(anObject)); 
          System.out.printf( "retained size: %d bytes\n" , meter.measureDeep(anObject)); 
          System.out.printf( "inner object count: %d\n" , meter.countChildren(anObject)); 
      } 
 }

Running the test produces the following output on my computer:

 ----------------------------------- 
 size: 24 bytes 
 retained size: 88 bytes 
 inner object count: 2 
 ----------------------------------- 
 size: 24 bytes 
 retained size: 128 bytes 
 inner object count: 2 
 ----------------------------------- 
 size: 24 bytes 
 retained size: 40 bytes 
 inner object count: 2 
 ----------------------------------- 
 size: 24 bytes 
 retained size: 136 bytes 
 inner object count: 4 
 ----------------------------------- 
 size: 24 bytes 
 retained size: 264 bytes 
 inner object count: 6

To conclude, you can see how it is easy to monitor the memory usage of your objects. It is very handy when dealing with huge collections, or when using caches such as the ones provided by Guava or EHCache. That way you can setup trigger that alert when memory consumption is excessive.

注意:

如果在调试的过程中,发现内存不足的情况,请调整JVM的启动参数。

JVM options: -Xms256m -Xmx256m.

文章选自:compute-java-object-memory-footprint-at.html

给我留言

留言无头像?


×
腾讯微博