The time overhead is of crucial concern to an online monitoring technique because high time overhead may degrade the performance of the investigated program, making the technique an impractical solution for real-world applications.
To accurately evaluate the time overhead of the proposed agent, we develop a simple program RuntimeExp. The source code of RuntimeExp can be found in Appendix B. During each execution of RuntimeExp, the program first allocates a total of 100 objects in heap, part of which are RuntimeExpMonitored objects and the rest are RuntimeExpNotMonitored objects. The number of RuntimeExpMonitored objects are determined according to user input. The program then executes a loop for 1000 iterations. In each iteration, each object is accessed twice (read and written, respectively). We then measure the total execution
Table 5.5: Result of the time overhead experiment Monitored Object Total Number of Accesses Execution Time
Overhead
time of these 1000 iterations of the RuntimeExp program with and without the Phase Two Part of our agent attached. When the agent is attached, all the RuntimeExpMonitored objects are monitored.
Table 5.5 shows the result of the time overhead experiment. For the RuntimeExp program executing without our agent attached, the average execution time of all 1000 iterations is 70ms; when the RuntimeExp program is executed with the proposed agent attached but monitors nothing in heap, the average execution time of all 1000 iterations is 71ms, which is very close to that without agent attached. This is because the Object Monitor Component does not have to handle any FieldAccess nor FieldModification events and thus no additional code is executed and no extra time overhead is incurred.
To better examine the relationship between total number of object accesses and exe-cution time, we plot the data in Table 5.5 as Figure 5.1. It can be observed from the plot that the time overhead is linearly proportional to the number of accesses during program execution. In worst case where all objects are monitored, the total execution time may grow to nearly 30 times, which is not tolerable in real-world applications. However, with the help of the offline analysis phase of the proposed agent, the user is able to effectively select a small portion of the objects. Moreover, the leaked objects basically are objects not frequently used during the long-term execution of programs. Thus online monitoring
Figure 5.1: Time overhead measurement of RuntimeExp
these infrequently used objects of small amount with the proposed agent incurs very little time overhead to the execution of the investigated program in most cases, and is therefore suitable for real-world application.
Chapter 6
Conclusions
We propose a two-phase approach to detect memory leaks due to useless references, adopting both offline analysis and online monitoring techniques. The Phase One Part (offline analysis) helps the user determine a set of classes whose objects are leak candidates.
These leak candidates are then monitored in the Phase Two Part (online monitoring), where the incurred time overhead can be significantly reduced at runtime with the benefit of partial monitoring.
For the demonstration purpose, we assume that the investigated programs are written in the Java language. The proposed approach uses an agent to communicate with the JVM. We test the proposed agent on Eclipse 3.1.2 and show that the report generated by the online monitoring phase of the agent is useful for locating the memory leak. Little per-object space overhead and nearly no time overhead are incurred during the execution of the investigated program due to partial monitoring, making it suitable for real-world applications.
As a final remark, the implementation of the proposed agent does not modify the JVM. Specifically, the proposed agent can be used in most JVMs that support JVMTI.
Bibliography
[1] R. Jones and R. Lins, Garbage collection: algorithms for automatic dynamic memory management. Wiley, 1996.
[2] E. K. Maxwell, G. Back, and N. Ramakrishnan, “Diagnosing memory leaks using graph mining on heap dumps,” in Proceedings of the 16th ACM SIGKDD interna-tional conference on Knowledge discovery and data mining, ser. KDD ’10. New York, NY, USA: ACM, 2010, pp. 115–124.
[3] Jprobe. Quest Software. [Online]. Available: http://www.quest.com/jprobe/
[4] M. D. Bond and K. S. McKinley, “Bell: bit-encoding online memory leak detection,”
SIGPLAN Not., vol. 41, pp. 61–72, October 2006.
[5] M. Jump and K. S. McKinley, “Detecting memory leaks in managed languages with cork,” Software: Practice and Experience, vol. 40, no. 1, pp. 1–22, 2010. [Online].
Available: http://dx.doi.org/10.1002/spe.945
[6] Jrockit mission control. Oracle. [Online]. Available: http://www.oracle.com/
technetwork/middleware/jrockit/overview/index-090630.html
[7] Jikes rvm. The Jikes RVM Project. [Online]. Available: http://jikesrvm.org/
[8] Oracle jrockit jvm. Oracle Corporation. [Online]. Available: http://www.oracle.
com/technetwork/middleware/jrockit/overview/index.html
[9] Java se hotspot. Oracle Corporation. [Online]. Available: http://www.oracle.com/
technetwork/java/javase/tech/hotspot-138757.html
[10] Jvm tool interface version 1.2. Oracle. [Online]. Available: http://docs.oracle.com/
javase/7/docs/platform/jvmti/jvmti.html
[11] K. D. Cooper, T. J. Harvey, and K. Kennedy, “A simple, fast dominance algorithm,”
2001. [Online]. Available: http://www.hipersoft.rice.edu/grads/publications/dom14.
[12] Eclipse bug 115789 - memory leak. The Eclipse Foundation. [Online]. Available:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=115789
Appendix A
The MyProgram Program
We design a sample Java program MyProgram to demonstrate the usage of the pro-posed agent. MyProgram consists of five files: MyProgram.java, test/MyDblLinkedList.java, test/MyListItem.java, test/MyDisplay.java and test/MySetting.java, whose source codes are listed below.
Source code of MyProgram.java:
1 import t e s t . * ; 2 import j a v a . i o . * ; 3 import j a v a . u t i l . Date ; 4 import j a v a . u t i l . TimeZone ; 5 import j a v a . t e x t . DateFormat ;
6 import j a v a . t e x t . SimpleDateFormat ; 7
8 public c l a s s MyProgram {
9 private s t a t i c void PrintMyDblLinkedList ( MyDblLinkedList d b l l i n k e d l i s t ) {
10 System . out . p r i n t ( " MyListItems : (from head to tail)\n" ) ; 11 MyListItem c u r r e n t = d b l l i n k e d l i s t . getHead ( ) ;
12
13 while ( c u r r e n t != null ) {
14 System . out . p r i n t ( " " + c u r r e n t . g e t V a l u e ( ) + "\t" ) ;
41 } 51 System . out . p r i n t ( " Generated MyDblLinkedList object instance :
dbllinkedlist \n" ) ;
68 int loop_count = I n t e g e r . p a r s e I n t ( a r g s [ j + 1 ] ) ;
82 long currentTime = System . nanoTime ( ) ;
83 e l a p s e d += currentTime − startTime ;
97 }
112 new SimpleDateFormat ( "HH:mm:ss" ) ;
113
114 dateFormat . setTimeZone ( TimeZone . getTimeZone ( "GMT"
) ) ;
122 // t h r e a d t o s l e e p f o r t h e s p e c i f i e d number o f experiment , Ctrl+Z to stop .\n" ) ;
134 try { i n 2 . r e a d L i n e ( ) ; } experiment , Ctrl+Z to stop .\n" ) ;
146 try { i n 2 . r e a d L i n e ( ) ; }
147 catch ( E x c e p t i o n e ) {
148 System . out . p r i n t l n ( "Caught an exception !" ) ;
3 public c l a s s MyDblLinkedList {
4 protected MyListItem head = null ; 5 protected int count = 0 ;
6 private MySetting s e t t i n g = null ; 7
8 public MyDblLinkedList ( MySetting s e t ) { 9 // add r e f e r e n c e t o MySet ting
24 } 25
26 public void removeHead ( ) { 27 i f ( count > 0 ) {
28 count −= 1 ;
29 MyListItem new_head = head . getNext ( ) ;
30 new_head . s e t P r e v ( null ) ; 31 t h i s . setHead ( new_head ) ;
32 }
33 }
34
35 public void setHead ( MyListItem item ) {
36 head = item ;
37 }
38
39 public MyListItem getHead ( ) {
40 return head ;
7
18 public MyListItem getNext ( ) {
19 return next ;
Source code of test/MyDisplay.java:
Appendix B
The RuntimeExp Program
We design a tiny Java program RuntimeExp to evaluate the runtime overhead of the proposed agent. RuntimeExp consists of three files: RuntimeExp.java, RuntimeExpMoni-tored.java and RuntimeExpNotMoniRuntimeExpMoni-tored.java, whose source codes are listed below.
Source code of RuntimeExp.java:
1 import j a v a . i o . * ;
2 import j a v a . u t i l . A r r a y L i s t ; 3 import j a v a . u t i l . Date ; 4 import j a v a . u t i l . TimeZone ; 5 import j a v a . t e x t . DateFormat ;
6 import j a v a . t e x t . SimpleDateFormat ; 7
8 public c l a s s RuntimeExp {
9 public s t a t i c A r r a y L i s t <RuntimeExpMonitored> monitored = new A r r a y L i s t <RuntimeExpMonitored >() ;
10 public s t a t i c A r r a y L i s t <RuntimeExpNotMonitored> not_monitored = new A r r a y L i s t <RuntimeExpNotMonitored >() ;
11 public s t a t i c void main ( S t r i n g [ ] a r g s ) {
12 try {
13 int p e r c e n t a g e = I n t e g e r . p a r s e I n t ( a r g s [ 0 ] ) ;
14 i f ( p e r c e n t a g e < 0 | | p e r c e n t a g e > 1 0 0 ) {
23 monitored . add (new RuntimeExpMonitored ( "A" + i ) ) ; 24
25 for ( int i = 0 ; i < r e m a i n i n g ; i ++)
26 not_monitored . add (new RuntimeExpNotMonitored ( "B" + i ) ) ; continue experiment or Ctrl+Z to stop." ) ;
32 try { i n . r e a d L i n e ( ) ; }
41
58 new SimpleDateFormat ( "HH:mm:ss" ) ; 59
60 dateFormat . setTimeZone ( TimeZone . getTimeZone ( "GMT" ) ) ; 61 long e l a p s e d = currentTime − startTime ;
70 System . out . p r i n t l n ( "Caught an exception !" ) ;
71 }
72
73 }
74 catch ( NumberFormatException e ) {
75 System . out . p r i n t l n ( "ERROR: " + e . getMessage ( ) ) ;
1 public c l a s s RuntimeExpMonitored { 2 private S t r i n g v a l u e ;
Source code of RuntimeExpNotMonitored.java:
1 public c l a s s RuntimeExpNotMonitored { 2 private S t r i n g v a l u e ;
3
4 public S t r i n g g e t ( ) { 5 return t h i s . v a l u e ;
6 }
7
8 public void s e t ( S t r i n g s t r ) { 9 t h i s . v a l u e = s t r ;
10 }
11
12 RuntimeExpNotMonitored ( S t r i n g s t r ) { 13 t h i s . s e t ( s t r ) ;
14 }
15 }