jruby-async-profiler 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.gitmodules +3 -0
- data/Gemfile +4 -0
- data/README.md +35 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/Rakefile +6 -0
- data/ext/async-profiler/.gitattributes +1 -0
- data/ext/async-profiler/.gitignore +6 -0
- data/ext/async-profiler/.travis.yml +11 -0
- data/ext/async-profiler/CHANGELOG.md +107 -0
- data/ext/async-profiler/JavaHome.class +0 -0
- data/ext/async-profiler/LICENSE +201 -0
- data/ext/async-profiler/Makefile +66 -0
- data/ext/async-profiler/README.md +487 -0
- data/ext/async-profiler/demo/SwingSet2.svg +2247 -0
- data/ext/async-profiler/docs/cddl1.txt +358 -0
- data/ext/async-profiler/profiler.sh +240 -0
- data/ext/async-profiler/src/allocTracer.cpp +155 -0
- data/ext/async-profiler/src/allocTracer.h +74 -0
- data/ext/async-profiler/src/arch.h +69 -0
- data/ext/async-profiler/src/arguments.cpp +265 -0
- data/ext/async-profiler/src/arguments.h +152 -0
- data/ext/async-profiler/src/codeCache.cpp +128 -0
- data/ext/async-profiler/src/codeCache.h +99 -0
- data/ext/async-profiler/src/engine.cpp +50 -0
- data/ext/async-profiler/src/engine.h +38 -0
- data/ext/async-profiler/src/flameGraph.cpp +770 -0
- data/ext/async-profiler/src/flameGraph.h +118 -0
- data/ext/async-profiler/src/flightRecorder.cpp +727 -0
- data/ext/async-profiler/src/flightRecorder.h +39 -0
- data/ext/async-profiler/src/frameName.cpp +189 -0
- data/ext/async-profiler/src/frameName.h +56 -0
- data/ext/async-profiler/src/itimer.cpp +49 -0
- data/ext/async-profiler/src/itimer.h +43 -0
- data/ext/async-profiler/src/jattach/jattach.c +437 -0
- data/ext/async-profiler/src/java/one/profiler/AsyncProfiler.java +160 -0
- data/ext/async-profiler/src/java/one/profiler/AsyncProfilerMXBean.java +43 -0
- data/ext/async-profiler/src/java/one/profiler/Counter.java +25 -0
- data/ext/async-profiler/src/java/one/profiler/Events.java +28 -0
- data/ext/async-profiler/src/javaApi.cpp +124 -0
- data/ext/async-profiler/src/lockTracer.cpp +161 -0
- data/ext/async-profiler/src/lockTracer.h +55 -0
- data/ext/async-profiler/src/mutex.cpp +33 -0
- data/ext/async-profiler/src/mutex.h +49 -0
- data/ext/async-profiler/src/os.h +45 -0
- data/ext/async-profiler/src/os_linux.cpp +129 -0
- data/ext/async-profiler/src/os_macos.cpp +115 -0
- data/ext/async-profiler/src/perfEvents.h +60 -0
- data/ext/async-profiler/src/perfEvents_linux.cpp +550 -0
- data/ext/async-profiler/src/perfEvents_macos.cpp +64 -0
- data/ext/async-profiler/src/profiler.cpp +952 -0
- data/ext/async-profiler/src/profiler.h +238 -0
- data/ext/async-profiler/src/spinLock.h +66 -0
- data/ext/async-profiler/src/stackFrame.h +57 -0
- data/ext/async-profiler/src/stackFrame_aarch64.cpp +75 -0
- data/ext/async-profiler/src/stackFrame_arm.cpp +58 -0
- data/ext/async-profiler/src/stackFrame_i386.cpp +82 -0
- data/ext/async-profiler/src/stackFrame_x64.cpp +113 -0
- data/ext/async-profiler/src/symbols.h +37 -0
- data/ext/async-profiler/src/symbols_linux.cpp +354 -0
- data/ext/async-profiler/src/symbols_macos.cpp +156 -0
- data/ext/async-profiler/src/vmEntry.cpp +173 -0
- data/ext/async-profiler/src/vmEntry.h +105 -0
- data/ext/async-profiler/src/vmStructs.cpp +104 -0
- data/ext/async-profiler/src/vmStructs.h +112 -0
- data/ext/async-profiler/src/wallClock.cpp +96 -0
- data/ext/async-profiler/src/wallClock.h +56 -0
- data/ext/async-profiler/test/AllocatingTarget.java +26 -0
- data/ext/async-profiler/test/LoadLibraryTest.java +21 -0
- data/ext/async-profiler/test/Target.java +31 -0
- data/ext/async-profiler/test/ThreadsTarget.java +35 -0
- data/ext/async-profiler/test/alloc-smoke-test.sh +36 -0
- data/ext/async-profiler/test/load-library-test.sh +35 -0
- data/ext/async-profiler/test/smoke-test.sh +37 -0
- data/ext/async-profiler/test/thread-smoke-test.sh +32 -0
- data/jruby-async-profiler.gemspec +32 -0
- data/lib/jruby/async/profiler.rb +10 -0
- data/lib/jruby/async/profiler/version.rb +7 -0
- metadata +155 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2017 Andrei Pangin
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
|
17
|
+
#ifndef _VMSTRUCTS_H
|
18
|
+
#define _VMSTRUCTS_H
|
19
|
+
|
20
|
+
#include <jvmti.h>
|
21
|
+
#include <stdint.h>
|
22
|
+
#include "codeCache.h"
|
23
|
+
|
24
|
+
|
25
|
+
class VMStructs {
|
26
|
+
protected:
|
27
|
+
static int _klass_name_offset;
|
28
|
+
static int _symbol_length_offset;
|
29
|
+
static int _symbol_length_and_refcount_offset;
|
30
|
+
static int _symbol_body_offset;
|
31
|
+
static int _class_klass_offset;
|
32
|
+
static int _thread_osthread_offset;
|
33
|
+
static int _osthread_id_offset;
|
34
|
+
static bool _has_perm_gen;
|
35
|
+
static jfieldID _eetop;
|
36
|
+
|
37
|
+
const char* at(int offset) {
|
38
|
+
return (const char*)this + offset;
|
39
|
+
}
|
40
|
+
|
41
|
+
public:
|
42
|
+
static void init(NativeCodeCache* libjvm);
|
43
|
+
|
44
|
+
static bool available() {
|
45
|
+
return _klass_name_offset >= 0
|
46
|
+
&& (_symbol_length_offset >= 0 || _symbol_length_and_refcount_offset >= 0)
|
47
|
+
&& _symbol_body_offset >= 0
|
48
|
+
&& _class_klass_offset >= 0;
|
49
|
+
}
|
50
|
+
|
51
|
+
static bool hasPermGen() {
|
52
|
+
return _has_perm_gen;
|
53
|
+
}
|
54
|
+
};
|
55
|
+
|
56
|
+
|
57
|
+
class VMSymbol : VMStructs {
|
58
|
+
public:
|
59
|
+
unsigned short length() {
|
60
|
+
if (_symbol_length_offset >= 0) {
|
61
|
+
return *(unsigned short*) at(_symbol_length_offset);
|
62
|
+
} else {
|
63
|
+
int length_and_refcount = *(unsigned int*) at(_symbol_length_and_refcount_offset);
|
64
|
+
return (length_and_refcount >> 16) & 0xffff;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
const char* body() {
|
69
|
+
return at(_symbol_body_offset);
|
70
|
+
}
|
71
|
+
};
|
72
|
+
|
73
|
+
class VMKlass : VMStructs {
|
74
|
+
public:
|
75
|
+
static VMKlass* fromHandle(uintptr_t handle) {
|
76
|
+
if (_has_perm_gen) {
|
77
|
+
// On JDK 7 KlassHandle is a pointer to klassOop, hence one more indirection
|
78
|
+
return (VMKlass*)(*(uintptr_t**)handle + 2);
|
79
|
+
} else {
|
80
|
+
return (VMKlass*)handle;
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
VMSymbol* name() {
|
85
|
+
return *(VMSymbol**) at(_klass_name_offset);
|
86
|
+
}
|
87
|
+
};
|
88
|
+
|
89
|
+
class java_lang_Class : VMStructs {
|
90
|
+
public:
|
91
|
+
VMKlass* klass() {
|
92
|
+
return *(VMKlass**) at(_class_klass_offset);
|
93
|
+
}
|
94
|
+
};
|
95
|
+
|
96
|
+
class VMThread : VMStructs {
|
97
|
+
public:
|
98
|
+
static bool available() {
|
99
|
+
return _eetop != NULL;
|
100
|
+
}
|
101
|
+
|
102
|
+
static VMThread* fromJavaThread(JNIEnv* env, jthread thread) {
|
103
|
+
return (VMThread*)(uintptr_t)env->GetLongField(thread, _eetop);
|
104
|
+
}
|
105
|
+
|
106
|
+
int osThreadId() {
|
107
|
+
const char* osthread = *(const char**) at(_thread_osthread_offset);
|
108
|
+
return *(int*)(osthread + _osthread_id_offset);
|
109
|
+
}
|
110
|
+
};
|
111
|
+
|
112
|
+
#endif // _VMSTRUCTS_H
|
@@ -0,0 +1,96 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2018 Andrei Pangin
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
|
17
|
+
#include <poll.h>
|
18
|
+
#include <string.h>
|
19
|
+
#include <signal.h>
|
20
|
+
#include <sys/types.h>
|
21
|
+
#include <unistd.h>
|
22
|
+
#include "wallClock.h"
|
23
|
+
#include "os.h"
|
24
|
+
#include "profiler.h"
|
25
|
+
|
26
|
+
|
27
|
+
const int THREADS_PER_TICK = 8;
|
28
|
+
|
29
|
+
long WallClock::_interval;
|
30
|
+
bool WallClock::_sample_idle_threads;
|
31
|
+
|
32
|
+
void WallClock::signalHandler(int signo, siginfo_t* siginfo, void* ucontext) {
|
33
|
+
Profiler::_instance.recordSample(ucontext, _interval, 0, NULL);
|
34
|
+
}
|
35
|
+
|
36
|
+
Error WallClock::start(Arguments& args) {
|
37
|
+
if (args._interval < 0) {
|
38
|
+
return Error("interval must be positive");
|
39
|
+
}
|
40
|
+
_interval = args._interval ? args._interval : DEFAULT_INTERVAL;
|
41
|
+
_sample_idle_threads = strcmp(args._event, EVENT_WALL) == 0;
|
42
|
+
|
43
|
+
OS::installSignalHandler(SIGPROF, signalHandler);
|
44
|
+
|
45
|
+
if (pipe(_pipefd) != 0) {
|
46
|
+
return Error("Unable to create poll pipe");
|
47
|
+
}
|
48
|
+
|
49
|
+
if (pthread_create(&_thread, NULL, threadEntry, this) != 0) {
|
50
|
+
close(_pipefd[1]);
|
51
|
+
close(_pipefd[0]);
|
52
|
+
return Error("Unable to create timer thread");
|
53
|
+
}
|
54
|
+
|
55
|
+
return Error::OK;
|
56
|
+
}
|
57
|
+
|
58
|
+
void WallClock::stop() {
|
59
|
+
char val = 1;
|
60
|
+
ssize_t r = write(_pipefd[1], &val, sizeof(val));
|
61
|
+
(void)r;
|
62
|
+
|
63
|
+
close(_pipefd[1]);
|
64
|
+
pthread_join(_thread, NULL);
|
65
|
+
close(_pipefd[0]);
|
66
|
+
}
|
67
|
+
|
68
|
+
void WallClock::timerLoop() {
|
69
|
+
ThreadList* thread_list = NULL;
|
70
|
+
|
71
|
+
int self = OS::threadId();
|
72
|
+
bool sample_idle_threads = _sample_idle_threads;
|
73
|
+
struct pollfd fds = {_pipefd[0], POLLIN, 0};
|
74
|
+
int timeout = _interval > 1000000 ? (int)(_interval / 1000000) : 1;
|
75
|
+
|
76
|
+
while (poll(&fds, 1, timeout) == 0) {
|
77
|
+
if (thread_list == NULL) {
|
78
|
+
thread_list = OS::listThreads();
|
79
|
+
}
|
80
|
+
|
81
|
+
for (int count = 0; count < THREADS_PER_TICK; ) {
|
82
|
+
int thread_id = thread_list->next();
|
83
|
+
if (thread_id == -1) {
|
84
|
+
delete thread_list;
|
85
|
+
thread_list = NULL;
|
86
|
+
break;
|
87
|
+
}
|
88
|
+
if (thread_id != self && (sample_idle_threads || OS::isThreadRunning(thread_id))) {
|
89
|
+
OS::sendSignalToThread(thread_id, SIGPROF);
|
90
|
+
count++;
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
delete thread_list;
|
96
|
+
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2018 Andrei Pangin
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
|
17
|
+
#ifndef _WALLCLOCK_H
|
18
|
+
#define _WALLCLOCK_H
|
19
|
+
|
20
|
+
#include <jvmti.h>
|
21
|
+
#include <signal.h>
|
22
|
+
#include <pthread.h>
|
23
|
+
#include "engine.h"
|
24
|
+
|
25
|
+
|
26
|
+
class WallClock : public Engine {
|
27
|
+
private:
|
28
|
+
static long _interval;
|
29
|
+
static bool _sample_idle_threads;
|
30
|
+
|
31
|
+
int _pipefd[2];
|
32
|
+
pthread_t _thread;
|
33
|
+
|
34
|
+
void timerLoop();
|
35
|
+
|
36
|
+
static void* threadEntry(void* wall_clock) {
|
37
|
+
((WallClock*)wall_clock)->timerLoop();
|
38
|
+
return NULL;
|
39
|
+
}
|
40
|
+
|
41
|
+
static void signalHandler(int signo, siginfo_t* siginfo, void* ucontext);
|
42
|
+
|
43
|
+
public:
|
44
|
+
const char* name() {
|
45
|
+
return _sample_idle_threads ? EVENT_WALL : EVENT_CPU;
|
46
|
+
}
|
47
|
+
|
48
|
+
const char* units() {
|
49
|
+
return "ns";
|
50
|
+
}
|
51
|
+
|
52
|
+
Error start(Arguments& args);
|
53
|
+
void stop();
|
54
|
+
};
|
55
|
+
|
56
|
+
#endif // _WALLCLOCK_H
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import java.util.Random;
|
2
|
+
|
3
|
+
public class AllocatingTarget implements Runnable {
|
4
|
+
public static volatile Object sink;
|
5
|
+
|
6
|
+
public static void main(String[] args) {
|
7
|
+
new Thread(new AllocatingTarget(), "AllocThread-1").start();
|
8
|
+
new Thread(new AllocatingTarget(), "AllocThread-2").start();
|
9
|
+
}
|
10
|
+
|
11
|
+
@Override
|
12
|
+
public void run() {
|
13
|
+
Random random = new Random();
|
14
|
+
while (true) {
|
15
|
+
allocate(random);
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
private static void allocate(Random random) {
|
20
|
+
if (random.nextBoolean()) {
|
21
|
+
sink = new int[128 * 1000];
|
22
|
+
} else {
|
23
|
+
sink = new Integer[128 * 1000];
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import java.lang.management.ClassLoadingMXBean;
|
2
|
+
import java.lang.management.ManagementFactory;
|
3
|
+
|
4
|
+
class LoadLibraryTest {
|
5
|
+
|
6
|
+
public static void main(String[] args) throws Exception {
|
7
|
+
for (int i = 0; i < 200; i++) {
|
8
|
+
Thread.sleep(10);
|
9
|
+
}
|
10
|
+
|
11
|
+
// Late load of libmanagement.so
|
12
|
+
ClassLoadingMXBean bean = ManagementFactory.getClassLoadingMXBean();
|
13
|
+
|
14
|
+
long n = 0;
|
15
|
+
while (n >= 0) {
|
16
|
+
n += bean.getLoadedClassCount();
|
17
|
+
n += bean.getTotalLoadedClassCount();
|
18
|
+
n += bean.getUnloadedClassCount();
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import java.io.File;
|
2
|
+
|
3
|
+
class Target {
|
4
|
+
private static volatile int value;
|
5
|
+
|
6
|
+
private static void method1() {
|
7
|
+
for (int i = 0; i < 1000000; ++i)
|
8
|
+
++value;
|
9
|
+
}
|
10
|
+
|
11
|
+
private static void method2() {
|
12
|
+
for (int i = 0; i < 1000000; ++i)
|
13
|
+
++value;
|
14
|
+
}
|
15
|
+
|
16
|
+
private static void method3() throws Exception {
|
17
|
+
for (int i = 0; i < 1000; ++i) {
|
18
|
+
for (String s : new File("/tmp").list()) {
|
19
|
+
value += s.hashCode();
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
public static void main(String[] args) throws Exception {
|
25
|
+
while (true) {
|
26
|
+
method1();
|
27
|
+
method2();
|
28
|
+
method3();
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import java.math.BigInteger;
|
2
|
+
|
3
|
+
public class ThreadsTarget {
|
4
|
+
public static void main(String[] args) {
|
5
|
+
new Thread(new Runnable() {
|
6
|
+
@Override
|
7
|
+
public void run() {
|
8
|
+
methodForThreadEarlyEnd();
|
9
|
+
}
|
10
|
+
}, "ThreadEarlyEnd").start();
|
11
|
+
new Thread(new Runnable() {
|
12
|
+
@Override
|
13
|
+
public void run() {
|
14
|
+
Thread.currentThread().setName("RenamedThread");
|
15
|
+
methodForRenamedThread();
|
16
|
+
}
|
17
|
+
}, "ThreadWillBeRenamed").start();
|
18
|
+
}
|
19
|
+
|
20
|
+
static void methodForThreadEarlyEnd() {
|
21
|
+
long now = System.currentTimeMillis();
|
22
|
+
BigInteger counter = BigInteger.ZERO;
|
23
|
+
while (System.currentTimeMillis() - now < 300) {
|
24
|
+
counter = counter.nextProbablePrime();
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
static void methodForRenamedThread() {
|
29
|
+
long now = System.currentTimeMillis();
|
30
|
+
BigInteger counter = BigInteger.ZERO;
|
31
|
+
while (System.currentTimeMillis() - now < 1000) {
|
32
|
+
counter = counter.nextProbablePrime();
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e # exit on any failure
|
4
|
+
set -x # print all executed lines
|
5
|
+
|
6
|
+
if [ -z "${JAVA_HOME}" ]; then
|
7
|
+
echo "JAVA_HOME is not set"
|
8
|
+
exit 1
|
9
|
+
fi
|
10
|
+
|
11
|
+
(
|
12
|
+
cd $(dirname $0)
|
13
|
+
|
14
|
+
if [ "AllocatingTarget.class" -ot "AllocatingTarget.java" ]; then
|
15
|
+
${JAVA_HOME}/bin/javac AllocatingTarget.java
|
16
|
+
fi
|
17
|
+
|
18
|
+
${JAVA_HOME}/bin/java AllocatingTarget &
|
19
|
+
|
20
|
+
FILENAME=/tmp/java.trace
|
21
|
+
JAVAPID=$!
|
22
|
+
|
23
|
+
sleep 1 # allow the Java runtime to initialize
|
24
|
+
../profiler.sh -f $FILENAME -o collapsed -d 5 -e alloc -t $JAVAPID
|
25
|
+
|
26
|
+
kill $JAVAPID
|
27
|
+
|
28
|
+
function assert_string() {
|
29
|
+
if ! grep -q "$1" $FILENAME; then
|
30
|
+
exit 1
|
31
|
+
fi
|
32
|
+
}
|
33
|
+
|
34
|
+
assert_string "\[AllocThread-1 tid=[0-9]\+\];.*AllocatingTarget.allocate;.*java.lang.Integer\[\]"
|
35
|
+
assert_string "\[AllocThread-2 tid=[0-9]\+\];.*AllocatingTarget.allocate;.*int\[\]"
|
36
|
+
)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e # exit on any failure
|
4
|
+
set -x # print all executed lines
|
5
|
+
|
6
|
+
if [ -z "${JAVA_HOME}" ]; then
|
7
|
+
echo "JAVA_HOME is not set"
|
8
|
+
exit 1
|
9
|
+
fi
|
10
|
+
|
11
|
+
(
|
12
|
+
cd $(dirname $0)
|
13
|
+
|
14
|
+
if [ "LoadLibraryTest.class" -ot "LoadLibraryTest.java" ]; then
|
15
|
+
${JAVA_HOME}/bin/javac LoadLibraryTest.java
|
16
|
+
fi
|
17
|
+
|
18
|
+
${JAVA_HOME}/bin/java LoadLibraryTest &
|
19
|
+
|
20
|
+
FILENAME=/tmp/java.trace
|
21
|
+
JAVAPID=$!
|
22
|
+
|
23
|
+
sleep 1 # allow the Java runtime to initialize
|
24
|
+
../profiler.sh -f $FILENAME -o collapsed -d 5 -i 1ms $JAVAPID
|
25
|
+
|
26
|
+
kill $JAVAPID
|
27
|
+
|
28
|
+
function assert_string() {
|
29
|
+
if ! grep -q "$1" $FILENAME; then
|
30
|
+
exit 1
|
31
|
+
fi
|
32
|
+
}
|
33
|
+
|
34
|
+
assert_string "Java_sun_management"
|
35
|
+
)
|