Permalink
Browse files

Add -Xdelay= commandline arg

This change adds a commandline arg to allow delaying by
the specified amount of milliseconds before enabling all
the registered recorders.
  • Loading branch information...
1 parent f250639 commit 8fecc9afb54f69638937e770c7471dacf9d847e8 norberthu committed Nov 15, 2012
View
@@ -11,8 +11,8 @@ and the callback code is only executed when the java agent is loaded.
heap allocations to stdout when removed. Be aware, a lot of recorders, including
nested ones, may be injected if the supplied matching pattern is not restrictive
enough.
-- HYBRID: This launches like the static use case but dynamically determins where
-to inject recorders.
+- HYBRID: This launches like the static use case but dynamically determines
+where to inject recorders.
Best way to understand what HeapAudit can do for you is to check out some of the
sample [tutorials](https://github.com/foursquare/heapaudit/blob/master/src/test/java/com/foursquare/heapaudit/tutorials/)
@@ -36,6 +36,7 @@ private static void help() {
" [ -Xoutput=<file> ] \n" +
" [ -Xrecorder=<class>@<jar> ] \n" +
" [ -Xthreaded ] \n" +
+ " [ -Xdelay=<milliseconds> ] \n" +
" [ -S<path> | \n" +
" -A<path> | \n" +
" -D<path> | \n" +
@@ -61,6 +62,8 @@ private static void help() {
"* Use -Xthreaded for dynamic use case to extend all recorders from the parent \n" +
" thread to the child thread. \n" +
" \n" +
+ "* Use -Xdelay to delay recording by the specified amount of milliseconds. \n" +
+ " \n" +
"* Use -S to suppress auditing a particular path and its sub calls. \n" +
"* Use -A to avoid auditing a particular path. \n" +
"* Use -D to debug instrumentation of a particular path. \n" +
@@ -137,21 +137,32 @@ public static boolean hasRecorders() {
static HeapRecorder[] getRecorders(Object context) {
- HeapCollection<HeapRecorder> localRecorders = ((NestedRecorders)context).recorders;
+ HeapRecorder[] recorders;
- HeapRecorder[] recorders = new HeapRecorder[globalRecorders.size() + localRecorders.size()];
+ if (HeapSettings.enabled) {
- int index = 0;
+ HeapCollection<HeapRecorder> localRecorders = ((NestedRecorders)context).recorders;
- for (HeapRecorder recorder: globalRecorders) {
+ recorders = new HeapRecorder[globalRecorders.size() + localRecorders.size()];
- recorders[index++] = recorder;
+ int index = 0;
- }
+ for (HeapRecorder recorder: globalRecorders) {
+
+ recorders[index++] = recorder;
+
+ }
+
+ for (HeapRecorder recorder: localRecorders) {
- for (HeapRecorder recorder: localRecorders) {
+ recorders[index++] = recorder;
+
+ }
+
+ }
+ else {
- recorders[index++] = recorder;
+ recorders = new HeapRecorder[0];
}
@@ -12,12 +12,20 @@
class HeapSettings {
- static void parse(String args) throws ClassNotFoundException, FileNotFoundException, IllegalAccessException, InstantiationException, MalformedURLException {
+ // The synchronized keyword is used on the parse method mostly to enforce a
+ // memory barrier across all of the global variables being set in the parse
+ // logic.
+
+ static synchronized void parse(String args) throws ClassNotFoundException, FileNotFoundException, IllegalAccessException, InstantiationException, MalformedURLException {
timeout = -1;
+ threaded = false;
+
conditional = false;
+ enabled = true;
+
lock = null;
output = System.out;
@@ -72,7 +80,7 @@ static void parse(String args) throws ClassNotFoundException, FileNotFoundExcept
}
- String value = (arg.length() > 2) ? arg.substring(2) : null;
+ final String value = (arg.length() > 2) ? arg.substring(2) : null;
switch (arg.charAt(1)) {
@@ -101,7 +109,7 @@ else if (value.startsWith("recorder=")) {
recorderClass = loader.loadClass(recorder[0]).asSubclass(HeapSummary.class);
}
- else if (value.startsWith("threaded")) {
+ else if (value.equals("threaded")) {
threaded = true;
@@ -111,6 +119,43 @@ else if (value.equals("conditional")) {
conditional = true;
}
+ else if (value.startsWith("delay=")) {
+
+ // NOTE: The enabled variable is NOT declared volatile.
+ // The synchronized keyword surrounding setting the
+ // enabled variable causes the compiler to insert memory
+ // barriers before and after modifying the value, thus
+ // flushing the change across threads on all processors.
+
+ enabled = false;
+
+ Thread thread = new Thread() {
+
+ public void run() {
+
+ try {
+
+ sleep(Long.parseLong(value.substring(6)));
+
+ } catch (java.lang.InterruptedException e) {
+
+ output.println(e);
+
+ }
+
+ synchronized (this) {
+
+ HeapSettings.enabled = true;
+
+ }
+
+ }
+
+ };
+
+ thread.start();
+
+ }
break;
@@ -174,6 +219,11 @@ else if (value.equals("conditional")) {
static boolean conditional = false;
+ // The enabled setting determines whether to send the allocations to the
+ // recorders.
+
+ static boolean enabled = true;
+
static FileChannel lock = null;
static PrintStream output = System.out;
@@ -406,6 +406,7 @@ public static void record(int count,
System.err.println(e);
}
+
}
}

0 comments on commit 8fecc9a

Please sign in to comment.