24 import java.io.*; |
24 import java.io.*; |
25 |
25 |
26 public class RedefineBigClassApp { |
26 public class RedefineBigClassApp { |
27 /** |
27 /** |
28 * Memory leak is assumed, if application consumes more than specified amount of memory during its execution. |
28 * Memory leak is assumed, if application consumes more than specified amount of memory during its execution. |
29 * The number is given in Kb. |
29 * The number is given in KB. |
30 */ |
30 */ |
31 private static final long MEM_LEAK_THRESHOLD = 32 * 1024; // 32Mb |
31 private static final long MEM_LEAK_THRESHOLD = 32 * 1024; // 32MB |
32 |
32 |
33 public static void main(String[] args) throws Exception { |
33 public static void main(String[] args) throws Exception { |
34 System.out.println("Creating instance of " + |
34 System.out.println("Creating instance of " + |
35 RedefineBigClassAgent.clz); |
35 RedefineBigClassAgent.clz); |
36 RedefineBigClassAgent.clz.newInstance(); |
36 RedefineBigClassAgent.clz.newInstance(); |
37 |
37 |
38 long vMemBefore = getVMemSize(); |
38 // Do a short warmup before creating the NMT baseline |
|
39 try { |
|
40 Thread.sleep(5 * 1000); |
|
41 } catch (InterruptedException ie) { |
|
42 } |
|
43 |
|
44 NMTHelper.baseline(); |
|
45 |
39 int count = 0; |
46 int count = 0; |
40 while (!RedefineBigClassAgent.doneRedefining) { |
47 while (!RedefineBigClassAgent.doneRedefining) { |
41 System.out.println("App loop count: " + ++count); |
48 System.out.println("App loop count: " + ++count); |
42 try { |
49 try { |
43 Thread.sleep(10 * 1000); |
50 Thread.sleep(10 * 1000); |
44 } catch (InterruptedException ie) { |
51 } catch (InterruptedException ie) { |
45 } |
52 } |
46 } |
53 } |
47 System.out.println("App looped " + count + " times."); |
54 System.out.println("App looped " + count + " times."); |
48 |
55 |
49 long vMemAfter = getVMemSize(); |
56 long committedDiff = NMTHelper.committedDiff(); |
50 if (vMemBefore == 0 || vMemAfter == 0) { |
57 if (committedDiff > MEM_LEAK_THRESHOLD) { |
51 System.err.println("WARNING: Cannot perform memory leak detection on this OS"); |
58 throw new Exception("FAIL: Committed memory usage increased by " + committedDiff + "KB " + |
52 } else { |
59 "(greater than " + MEM_LEAK_THRESHOLD + "KB)"); |
53 long vMemDelta = vMemAfter - vMemBefore; |
|
54 if (vMemDelta > MEM_LEAK_THRESHOLD) { |
|
55 System.err.println("FAIL: Virtual memory usage increased by " + vMemDelta + "Kb " + |
|
56 "(greater than " + MEM_LEAK_THRESHOLD + "Kb)"); |
|
57 System.exit(1); |
|
58 } |
|
59 System.err.println("PASS: Virtual memory usage increased by " + vMemDelta + "Kb " + |
|
60 "(not greater than " + MEM_LEAK_THRESHOLD + "Kb)"); |
|
61 } |
60 } |
62 System.exit(0); |
61 System.err.println("PASS: Committed memory usage increased by " + committedDiff + "KB " + |
63 } |
62 "(not greater than " + MEM_LEAK_THRESHOLD + "KB)"); |
64 |
|
65 /** |
|
66 * Return size of virtual memory allocated to the process in Kb. |
|
67 * Linux specific. On other platforms and in case of any errors return 0. |
|
68 */ |
|
69 private static long getVMemSize() { |
|
70 |
|
71 // Refer to the Linux proc(5) man page for details about /proc/self/stat file |
|
72 // |
|
73 // In short, this file contains status information about the current process |
|
74 // written in one line. The fields are separated with spaces. |
|
75 // The 23rd field is defined as 'vsize %lu Virtual memory size in bytes' |
|
76 |
|
77 try (FileReader fileReader = new FileReader("/proc/self/stat"); |
|
78 BufferedReader bufferedReader = new BufferedReader(fileReader)) { |
|
79 String line = bufferedReader.readLine(); |
|
80 return Long.parseLong(line.split(" ")[22]) / 1024; |
|
81 } catch (Exception ex) {} |
|
82 return 0; |
|
83 } |
63 } |
84 } |
64 } |