Skip to content

Commit 6a2f05c

Browse files
committed
Initial commit
0 parents  commit 6a2f05c

File tree

6 files changed

+1318
-0
lines changed

6 files changed

+1318
-0
lines changed

.gitignore

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
target/
2+
!.mvn/wrapper/maven-wrapper.jar
3+
!**/src/main/**/target/
4+
!**/src/test/**/target/
5+
6+
### IntelliJ IDEA ###
7+
.idea/modules.xml
8+
.idea/jarRepositories.xml
9+
.idea/compiler.xml
10+
.idea/libraries/
11+
*.iws
12+
*.iml
13+
*.ipr
14+
15+
### VS Code ###
16+
.vscode/
17+
18+
### Mac OS ###
19+
.DS_Store
20+
/ap-releases/async-profiler-*

README.md

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
Loader for AsyncProfiler
2+
========================
3+
4+
Packages [async-profiler](https://github.com/jvm-profiling-tools/async-profiler) releases in a JAR
5+
with a `AsyncProfilerLoader` that loads the suitable native library for the current platform.
6+
7+
This is usable as a java agent (same arguments as the async-profiler agent) and as the basis for other libraries.
8+
The real rationale behind this library is that the async-profiler is a nice tool, but it cannot be easily integrated
9+
into other Java based tools.
10+
11+
Take the `all` build and you have a JAR that provides the important features of async-profiler on all supported platforms:
12+
13+
A changelog can be found at the async-profiler repository, as this library should rarely change itself.
14+
15+
Supported Platforms
16+
-------------------
17+
18+
- Required Java version: 8 or higher
19+
- Supported OS: Linux and macOS (on all platforms the async-profiler has binaries for)
20+
21+
Variants
22+
--------
23+
The JAR can be obtained in the following variants:
24+
25+
- `macos`, `linux-x64`, ...: `jattach`, `profiler.sh` and `libasyncProfiler.so` for the given platform
26+
- `all`: all of the above
27+
28+
Commands
29+
--------
30+
31+
The following is a more in-depth description of the commands of `java -jar ap-loader.jar`.
32+
33+
Be aware that it is recommended to use run the JVM with the
34+
`-XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints` flags when attaching to a running JVM.
35+
This improves the accuracy of the profiler.
36+
37+
Overview over the commands:
38+
39+
```sh
40+
Usage: java -jar ap-loader.jar <command> [args]
41+
Commands:
42+
help show this help
43+
jattach run the included jattach binary
44+
profiler run the included profiler.sh
45+
supported fails if this JAR does not include a profiler for the current OS and architecture
46+
converter run the included converter JAR
47+
version version of the included async-profiler
48+
clear clear the directory used for storing extracted files
49+
```
50+
51+
### jattach
52+
53+
`java -jar ap-loader.jar jattach` is equivalent to calling the suitable `jattach` binary
54+
from [GitHub](https://github.com/apangin/jattach)>:
55+
56+
```sh
57+
# Load a native agent
58+
java -jar ap-loader.jar jattach <pid> load <.so-path> { true | false, is path absolute? } [ options ]
59+
60+
# Load a java agent
61+
java -jar ap-loader.jar jattach <pid> load instrument false "javaagent.jar=arguments"
62+
63+
# Running the help command for jcmd
64+
java -jar ap-loader.jar jattach <pid> jcmd "help -all"
65+
```
66+
67+
See the [GitHub page of jattach](https://github.com/apangin/jattach) for more details.
68+
69+
### profiler
70+
`java -jar ap-loader.jar profiler` is equivalent to calling the suitable `profiler.sh`:
71+
72+
```sh
73+
# Profile a process for a `n` seconds
74+
java -jar ap-loader.jar profiler -d <n> <pid>
75+
76+
# Profile a process for allocation, CPU and lock events and save the results to a JFR file
77+
java -jar ap-loader.jar profiler -e alloc,cpu,lock -f <file.jfr> <pid>
78+
```
79+
80+
See the [GitHub page of async-profiler](https://github.com/jvm-profiling-tools/async-profiler) for more details.
81+
82+
### supported
83+
84+
Allows you to check whether your JAR includes a `jattact`, `profile.sh` and `libasyncProfiler.so` for
85+
your current OS and architecture.
86+
87+
### converter
88+
89+
`java -jar ap-loader.jar converter` is equivalent to calling the included `jconverter.jar`:
90+
91+
```sh
92+
java -jar ap-loader.jar converter <Converter> [options] <input> <output>
93+
94+
# Convert a JFR file to flame graph
95+
java -jar ap-loader.jar converter jfr2flame <input.jfr> <output.html>
96+
```
97+
98+
The available converters depend on the included async-profiler version.
99+
Call `java -jar converter` to a list of available converters, see
100+
[the source code on GitHub](https://github.com/jvm-profiling-tools/async-profiler/blob/master/src/converter/Main.java)
101+
for more details.
102+
103+
### clear
104+
105+
Clear the application directory used for storing extracted files,
106+
like `/Users/<user>/Library/Application Support/me.bechberger.ap-loader-<version>/`
107+
to redo the extraction on the next run.
108+
109+
110+
Running as an agent
111+
-------------------
112+
113+
`java -javaagent:ap-loader.jar=<options>` is equivalent to `java -agentpath:libasyncProfiler.so=<options>`
114+
with the suitable library.
115+
This can be used to profile a Java process from the start.
116+
117+
```sh
118+
# Profile the application and output a flamegraph
119+
java -javaagent:/path/to/libasyncProfiler.so=start,event=cpu,file=profile.html <java arguments>
120+
```
121+
122+
See the [GitHub page of async-profiler](https://github.com/jvm-profiling-tools/async-profiler) for more details.
123+
124+
Using in Java code
125+
------------------
126+
127+
Then you can use the `AsyncProfilerLoader` class to load the native library:
128+
129+
```java
130+
AsyncProfiler profiler + one.profiler.AsyncProfilerLoader.load();
131+
```
132+
133+
`AsyncProfiler` is the [main API class](https://github.com/jvm-profiling-tools/async-profiler/blob/master/src/api/one/profiler/AsyncProfiler.java)
134+
from the async-profiler.jar.
135+
136+
The API of the `AsyncProfilerLoader` can be used to execute all commands the CLI programmatically.
137+
138+
### Snapsshots
139+
We currently only release to snapshop, as the API is not stable yet.
140+
141+
```xml
142+
<dependency>
143+
<groupId>me.bechberger</groupId>
144+
<artifactId>ap-loader</artifactId>
145+
<version>version-variant-SNAPSHOT</version>
146+
</dependency>
147+
```
148+
149+
For example for the all variant of version 2.8.3:
150+
```xml
151+
<dependency>
152+
<groupId>me.bechberger</groupId>
153+
<artifactId>ap-loader</artifactId>
154+
<version>2.8.3-all-SNAPSHOT</version>
155+
</dependency>
156+
```
157+
158+
You also have to add the snapshot repository:
159+
```xml
160+
<repositories>
161+
<repository>
162+
<id>snapshots</id>
163+
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
164+
<releases>
165+
<enabled>false</enabled>
166+
</releases>
167+
<snapshots>
168+
<enabled>true</enabled>
169+
</snapshots>
170+
</repository>
171+
</repositories>
172+
```
173+
174+
175+
Build and test
176+
--------------
177+
178+
The following describes how to build the different JARs and how to test them.
179+
It requires a platform supported by async-profiler and Python 3.6+.
180+
181+
### Build the JARs using maven
182+
183+
```sh
184+
# download and unzip the platform releases that you want to include
185+
wget https://github.com/jvm-profiling-tools/async-profiler/releases/download/v2.8.3/async-profiler-2.8.3-macos.zip
186+
unzip -o async-profiler-2.8.3-macos.zip -d ap-releases
187+
# build the JAR for the release
188+
# maven might throw warnings, related to the project version setting,
189+
# but the alternative solutions don't work, so we ignore the warning for now
190+
mvn -Dproject.versionPlatform=2.8.3-macos assembly:single
191+
# use it
192+
java -jar target/ap-loader-2.8.3-macos-full.jar ...
193+
# build the all JAR
194+
mvn -Dproject.versionPlatform=2.8.3-all -f pom_all.xml assembly:single
195+
```
196+
197+
Development
198+
-----------
199+
This project is written in Java 8, to support all relevant platforms.
200+
The feature set should not increase beyond what is currently:
201+
Just build your library on top of it. But I'm of course happy for bug reports and fixes.
202+
203+
The code is formatted using [google-java-format](https://github.com/google/google-java-format).
204+
205+
License
206+
-------
207+
Apache 2.0

bin/copy_all_libs.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#! /bin/sh
2+
# ./copy_all_libs.sh <base_dir> <artifact version, like 2.8.3-all
3+
4+
set -e
5+
6+
# extract the version without the platform suffix
7+
version=$(echo "$2" | cut -d '-' -f 1)
8+
echo "version: $version"
9+
cd "$1" || exit 1
10+
mkdir -p target/classes/libs
11+
for f in ap-releases/async-profiler-$version-*; do
12+
if (echo "$f" | grep 'code' || echo "$f" | grep ".tar.gz" || echo "$f" | grep ".zip"); then
13+
continue
14+
fi
15+
# extract the platform suffix
16+
platform=$(echo "$f" | cut -d '-' -f 5-10)
17+
# copy the library
18+
echo "Copying $f/build/libasyncProfiler.so for platform $platform"
19+
cp "$f/build/libasyncProfiler.so" "target/classes/libs/libasyncProfiler-$platform.so"
20+
echo "Copying $f/build/jattach for platform $platform"
21+
cp "$f/build/jattach" "target/classes/libs/jattach-$platform"
22+
echo "Copying $f/profiler.sh for platform $platform"
23+
cp "$f/profiler.sh" "target/classes/libs/profiler-$platform.sh"
24+
done
25+
first_folder=$(echo ap-releases/async-profiler-$version-linux* | cut -d " " -f 1)
26+
# copy the converter
27+
echo "Copy $first_folder/build/converter.jar"
28+
cp "$first_folder/build/converter.jar" "target/classes/libs/converter.jar"
29+
# extract the async-profiler JAR
30+
echo "Extracting $first_folder/build/async-profiler.jar"
31+
ls target/classes/libs >target/classes/libs/index
32+
unzip -o $first_folder/build/async-profiler* "*.class" -d target/classes

0 commit comments

Comments
 (0)