18 |
19 | -agentlib: 后面的名称是要加载的库的名称. 扩展为操作系统特定的文件名。 将在启动时传递给代理。 例如,如果指定选项-agentlib:foo=opt1,opt2,则VM会尝试从Windows下的系统PATH加载共享库foo.dll,或者Solaris运行环境下从LD_LIBRARY_PATH加载libfoo.so。在`mac`操作系统下不需要设置LD_LIBRARY_PATH ,java 二进制文件将通过它自己的运行路径查找它所依赖的库blifoo.dylib, 如果代理库静态链接到可执行文件中,则不会发生实际加载.
20 |
21 |
22 | * -agentpath:\=\
23 |
24 | -agentpath: 后面的路径是加载库的绝对路径。 不会发生库名扩展。 将在启动时传递给代理。 例如,如果指定选项
25 | -agentpath:c:\myLibs\foo.dll=opt1,opt2,VM 将尝试加载共享库 c:\myLibs\foo.dll。 如果代理库静态链接到可执行文件中,则不会发生实际加载。
26 |
27 | * -agentlib:jdwp=\
28 |
29 | 如果JVMTI代理需要特定的库,例如 jdwp,则可以在启动时指定路径.
30 |
31 | ## 生命周期
32 | 代理有两种启动方式,每个代理只调用一次启动函数。
33 | * 代理跟随目标JVM一起启动 Agent_OnLoad函数将会被调用
34 | * 附加到已启动的JVM上 Agent_OnAttach函数将会被调用
35 |
36 | 代理结束时会执行Agent_OnUnload函数(可选)
37 |
38 | > 代理必须包含jvmti.h带有以下语句的文件:`#include `,并且必须包含一个`Agent_OnLoad`函数.
39 |
40 |
41 | ## JVMTI的事件处理
42 |
43 | JVMTI依赖于每个事件的回调.一般会在`Agent_OnLoad`函数中添加事件的回调,例如要使用`InterruptThread`功能,则`can_signal_thread`功能必须打开.
44 | ```c++
45 | // JVMTI所支持的功能
46 | typedef struct {
47 | unsigned int can_tag_objects : 1;
48 | unsigned int can_generate_field_modification_events : 1;
49 | unsigned int can_generate_field_access_events : 1;
50 | unsigned int can_get_bytecodes : 1;
51 | unsigned int can_get_synthetic_attribute : 1;
52 | unsigned int can_get_owned_monitor_info : 1;
53 | unsigned int can_get_current_contended_monitor : 1;
54 | unsigned int can_get_monitor_info : 1;
55 | unsigned int can_pop_frame : 1;
56 | unsigned int can_redefine_classes : 1;
57 | unsigned int can_signal_thread : 1;
58 | unsigned int can_get_source_file_name : 1;
59 | unsigned int can_get_line_numbers : 1;
60 | unsigned int can_get_source_debug_extension : 1;
61 | unsigned int can_access_local_variables : 1;
62 | unsigned int can_maintain_original_method_order : 1;
63 | unsigned int can_generate_single_step_events : 1;
64 | unsigned int can_generate_exception_events : 1;
65 | unsigned int can_generate_frame_pop_events : 1;
66 | unsigned int can_generate_breakpoint_events : 1;
67 | unsigned int can_suspend : 1;
68 | unsigned int can_redefine_any_class : 1;
69 | unsigned int can_get_current_thread_cpu_time : 1;
70 | unsigned int can_get_thread_cpu_time : 1;
71 | unsigned int can_generate_method_entry_events : 1;
72 | unsigned int can_generate_method_exit_events : 1;
73 | unsigned int can_generate_all_class_hook_events : 1;
74 | unsigned int can_generate_compiled_method_load_events : 1;
75 | unsigned int can_generate_monitor_events : 1;
76 | unsigned int can_generate_vm_object_alloc_events : 1;
77 | unsigned int can_generate_native_method_bind_events : 1;
78 | unsigned int can_generate_garbage_collection_events : 1;
79 | unsigned int can_generate_object_free_events : 1;
80 | unsigned int can_force_early_return : 1;
81 | unsigned int can_get_owned_monitor_stack_depth_info : 1;
82 | unsigned int can_get_constant_pool : 1;
83 | unsigned int can_set_native_method_prefix : 1;
84 | unsigned int can_retransform_classes : 1;
85 | unsigned int can_retransform_any_class : 1;
86 | unsigned int can_generate_resource_exhaustion_heap_events : 1;
87 | unsigned int can_generate_resource_exhaustion_threads_events : 1;
88 | unsigned int : 7;
89 | unsigned int : 16;
90 | unsigned int : 16;
91 | unsigned int : 16;
92 | unsigned int : 16;
93 | unsigned int : 16;
94 | } jvmtiCapabilities;
95 |
96 | // JVMTI 所支持的事件类型
97 | typedef enum {
98 | JVMTI_MIN_EVENT_TYPE_VAL = 50,
99 | JVMTI_EVENT_VM_INIT = 50,
100 | JVMTI_EVENT_VM_DEATH = 51,
101 | JVMTI_EVENT_THREAD_START = 52,
102 | JVMTI_EVENT_THREAD_END = 53,
103 | JVMTI_EVENT_CLASS_FILE_LOAD_HOOK = 54,
104 | JVMTI_EVENT_CLASS_LOAD = 55,
105 | JVMTI_EVENT_CLASS_PREPARE = 56,
106 | JVMTI_EVENT_VM_START = 57,
107 | JVMTI_EVENT_EXCEPTION = 58,
108 | JVMTI_EVENT_EXCEPTION_CATCH = 59,
109 | JVMTI_EVENT_SINGLE_STEP = 60,
110 | JVMTI_EVENT_FRAME_POP = 61,
111 | JVMTI_EVENT_BREAKPOINT = 62,
112 | JVMTI_EVENT_FIELD_ACCESS = 63,
113 | JVMTI_EVENT_FIELD_MODIFICATION = 64,
114 | JVMTI_EVENT_METHOD_ENTRY = 65,
115 | JVMTI_EVENT_METHOD_EXIT = 66,
116 | JVMTI_EVENT_NATIVE_METHOD_BIND = 67,
117 | JVMTI_EVENT_COMPILED_METHOD_LOAD = 68,
118 | JVMTI_EVENT_COMPILED_METHOD_UNLOAD = 69,
119 | JVMTI_EVENT_DYNAMIC_CODE_GENERATED = 70,
120 | JVMTI_EVENT_DATA_DUMP_REQUEST = 71,
121 | JVMTI_EVENT_MONITOR_WAIT = 73,
122 | JVMTI_EVENT_MONITOR_WAITED = 74,
123 | JVMTI_EVENT_MONITOR_CONTENDED_ENTER = 75,
124 | JVMTI_EVENT_MONITOR_CONTENDED_ENTERED = 76,
125 | JVMTI_EVENT_RESOURCE_EXHAUSTED = 80,
126 | JVMTI_EVENT_GARBAGE_COLLECTION_START = 81,
127 | JVMTI_EVENT_GARBAGE_COLLECTION_FINISH = 82,
128 | JVMTI_EVENT_OBJECT_FREE = 83,
129 | JVMTI_EVENT_VM_OBJECT_ALLOC = 84,
130 | JVMTI_MAX_EVENT_TYPE_VAL = 84
131 | } jvmtiEvent;
132 | ```
133 |
134 |
135 | ```C++
136 | jvmtiCapabilities capabilities = {0};
137 | // 设置所支持的功能
138 | capabilities.can_generate_exception_events = 1;
139 | capabilities.can_get_bytecodes = 1;
140 | capabilities.can_get_constant_pool = 1;
141 | // 使用AddCapabilities函数将其添加到JVMTI环境中
142 | jvmti->AddCapabilities(&capabilities);
143 |
144 | // 注册事件通知 启用了VM初始化,异常,线程启动和结束等几个事件,注册的每个事件都必须有一个指定的回调函数, 如当生类型为Exception的事件时,会调用ExceptionCallback
145 | jvmtiEventCallbacks callbacks = {0};
146 | callbacks.VMInit = VMInit;
147 | callbacks.Exception = ExceptionCallback;
148 | callbacks.ThreadStart = ThreadStartCallback;
149 | callbacks.ThreadEnd = ThreadEndCallback;
150 | jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
151 | jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL);
152 | jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_EXCEPTION, NULL);
153 | jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_THREAD_START, NULL);
154 | jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_THREAD_END, NULL);
155 | ```
156 |
157 | ## see also
158 | [JVM事件处理](https://github.com/openjdk/jdk/blob/jdk8-b120/jdk/src/share/back/eventHandler.c)
159 | [JVMTI](https://github.com/openjdk/jdk/blob/jdk8-b120/jdk/src/share/javavm/export/jvmti.h)
160 |
--------------------------------------------------------------------------------
/src/autorun/jvm/jvmti/README.md:
--------------------------------------------------------------------------------
1 | # JVM TI tools
2 |
3 | Collection of small Java serviceability improvements based on
4 | [JVM Tool Interface](https://docs.oracle.com/en/java/javase/11/docs/specs/jvmti.html).
5 |
6 | - [richNPE](#richnpe)
7 | - [vmtrace](#vmtrace)
8 | - [antimodule](#antimodule)
9 | - [heapsampler](#heapsampler)
10 | - [faketime](#faketime)
11 | - [methodCalledCount](#methodCalledCount)
12 |
13 | ## richNPE
14 |
15 | Enhances `NullPointerException` thrown by JVM with a detailed error message.
16 |
17 | For example, there are several reasons why the following code may throw `NullPointerException`:
18 |
19 | long value = source.map().get(key);
20 |
21 | Either
22 |
23 | - `source` is null, or
24 | - `map()` returns null, or
25 | - `get()` returns null and the subsequent unboxing fails.
26 |
27 | The standard JDK exception message does not give a clue which expression exactly caused NPE,
28 | but when using this tool, the message will look like
29 |
30 | java.lang.NullPointerException: Called method 'get()' on null object at bci 19
31 |
32 | While [JDK-8218628](https://bugs.openjdk.java.net/browse/JDK-8218628) is going to be implemented
33 | in JDK 13, the given agent improves NPE messages for existing JDK 8-12.
34 |
35 | #### Compilation
36 |
37 | # Linux
38 | g++ -O2 -fPIC -shared -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -olibrichNPE.so richNPE.cpp
39 |
40 | # Windows
41 | cl /O2 /LD /I "%JAVA_HOME%/include" -I "%JAVA_HOME%/include/win32" richNPE.cpp
42 |
43 | #### Usage
44 |
45 | java -agentpath:/path/to/librichNPE.so MainClass
46 |
47 |
48 | ## vmtrace
49 |
50 | Traces basic JVM events like
51 |
52 | - [Thread started / terminated](stackframe/stackframe.cpp)
53 | - GC started / finished
54 | - Class loading / class prepared
55 | - Method compiled / unloaded
56 | - Dynamic code generated
57 |
58 | #### Example output
59 |
60 | ```text
61 | [0.05588] Method compiled: java/lang/String. (1056 bytes)
62 | [0.05597] Loading class: java/io/FileOutputStream$1 (557 bytes)
63 | [0.05600] Class prepared: java/io/FileOutputStream$1
64 | [0.05602] Method compiled: java/lang/String.hashCode (512 bytes)
65 | [0.05618] Thread started: main
66 | [0.05622] Loading class: sun/launcher/LauncherHelper (14692 bytes)
67 | [0.05640] Dynamic code generated: I2C/C2I adapters(0xabbebebea0000000)@0x00000000032c38a0 (392 bytes)
68 | [0.05642] Dynamic code generated: I2C/C2I adapters(0xbebebea0)@0x00000000032c36a0 (376 bytes)
69 | ...
70 | ```
71 |
72 | #### Compilation
73 |
74 | # Linux
75 | g++ -O2 -fPIC -shared -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -olibvmtrace.so vmtrace.cpp
76 |
77 | # Windows
78 | cl /O2 /LD /I "%JAVA_HOME%/include" -I "%JAVA_HOME%/include/win32" vmtrace.cpp
79 |
80 | #### Usage
81 |
82 | java -agentpath:/path/to/libvmtrace.so[=output.log] MainClass
83 |
84 | The log will be written to the file specified in the agent arguments,
85 | or to `stderr` if no arguments given.
86 |
87 |
88 | ## antimodule
89 |
90 | Removes Jigsaw restrictions in JDK 9+ by opening and exporting all
91 | JDK modules to the unnamed module.
92 |
93 | This allows Reflection access to all JDK private fields and methods
94 | with no warnings, even when `--illegal-access=deny` option specified.
95 | This also makes all JDK internal classes like `sun.nio.ch.DirectBuffer`
96 | accessible by the unnamed module.
97 |
98 | The agent is helpful for running older Java applications on JDK 9+
99 | when application uses private APIs.
100 |
101 | #### Compilation
102 |
103 | # Linux
104 | g++ -O2 -fPIC -shared -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -olibantimodule.so antimodule.cpp
105 |
106 | # Windows
107 | cl /O2 /LD /I "%JAVA_HOME%/include" -I "%JAVA_HOME%/include/win32" antimodule.cpp
108 |
109 | #### Usage
110 |
111 | java -agentpath:/path/to/libantimodule.so MainClass
112 |
113 |
114 | ## heapsampler
115 |
116 | The example of low-overhead heap allocation profiler based on
117 | [JEP 331](https://openjdk.java.net/jeps/331).
118 |
119 | Requires JDK 11 or later.
120 |
121 | #### Example output
122 |
123 | The output is generated in collapsed stacktraces format suitable for
124 | generating [Flame Graphs](https://github.com/brendangregg/FlameGraph/).
125 |
126 | ```text
127 | Allocate.main;java.lang.Long.valueOf;java.lang.Long 49
128 | Allocate.main;java.lang.Object[] 31
129 | java.lang.Thread.run;jdk.internal.misc.Signal$1.run;java.lang.Terminator$1.handle;java.lang.Class 1
130 | jdk.internal.misc.Signal.dispatch;java.lang.Class 1
131 | ```
132 |
133 | See [async-profiler](https://github.com/jvm-profiling-tools/async-profiler)
134 | for more information about allocation profiling and Flame Graphs.
135 | Note that `heapsampler` works only on JDK 11+, while `async-profiler`
136 | is capable of generating allocation profiles on JDK 7+.
137 |
138 | #### Compilation
139 |
140 | # Linux
141 | g++ -O2 -fPIC -shared -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -olibheapsampler.so heapsampler.cpp
142 |
143 | # Windows
144 | cl /O2 /LD /I "%JAVA_HOME%/include" -I "%JAVA_HOME%/include/win32" heapsampler.cpp
145 |
146 | #### Usage
147 |
148 | java -agentpath:/path/to/libheapsampler.so[=interval] MainClass > output.txt
149 |
150 | The agent can be also loaded dynamically in run-time:
151 |
152 | jcmd JVMTI.agent_load /path/to/libheapsampler.so [interval]
153 |
154 | The optional `interval` argument specifies the sampling interval in bytes.
155 | The default value is 512 KB.
156 | The output is printed on `stdout`.
157 |
158 |
159 | ## faketime
160 |
161 | Changes current date/time for a Java application without affecting system date/time.
162 |
163 | The agent rebinds the native entry for `System.currentTimeMillis` and related methods
164 | and adds the specified offset to the times returned by these methods.
165 |
166 | #### Compilation
167 |
168 | # Linux
169 | g++ -O2 -fPIC -shared -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -olibfaketime.so faketime.cpp
170 |
171 | # Windows
172 | cl /O2 /LD /I "%JAVA_HOME%/include" -I "%JAVA_HOME%/include/win32" faketime.cpp
173 |
174 | #### Usage
175 |
176 | java -agentpath:/path/to/libfaketime.so=timestamp|+-offset MainClass
177 |
178 | where the agent argument is either
179 |
180 | - absolute `timestamp` in milliseconds from Epoch, or
181 | - relative `offset` in milliseconds, if `offset` starts with `+` or `-`
182 |
183 | Since `System.currentTimeMillis` is a JVM intrinsic method, it's also required to disable
184 | the corresponding intrinsic to make sure the JNI method is called:
185 |
186 | java -XX:+UnlockDiagnosticVMOptions -XX:DisableIntrinsic=_currentTimeMillis -XX:CompileCommand=dontinline,java.lang.System::currentTimeMillis
187 |
188 |
189 | ## methodCalledCount
190 |
191 | Count the number of times each method is called. Print the number of calls to all methods when unload agent.
192 |
193 | #### Compilation
194 |
195 | # Linux
196 | g++ -O2 -fPIC -shared -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -o liba.so methodCalledCount.cpp
197 |
198 | # mac
199 | g++ -O2 -fPIC -shared -I $JAVA_HOME/include -I $JAVA_HOME/include/darwin -o liba.dylib methodCalledCount.cpp
200 |
201 | # Windows
202 | cl /O2 /LD /I "%JAVA_HOME%/include" -I "%JAVA_HOME%/include/win32" methodCalledCount.cpp
203 |
204 |
205 | #### Usage
206 |
207 | java -agentpath:/path/to/liba.dylib MainClass
208 |
209 |
210 | #### Example output
211 | ```text
212 | Method name: AbstractCollection.java# called 8 nums.
213 | Method name: AbstractList.java# called 6 nums.
214 | Method name: AbstractMap.java# called 7 nums.
215 | Method name: AbstractSequentialList.java# called 4 nums.
216 | Method name: AbstractSet.java# called 1 nums.
217 | Method name: AbstractStringBuilder.java# called 71 nums.
218 | Method name: AbstractStringBuilder.java#append called 196 nums.
219 | Method name: AbstractStringBuilder.java#ensureCapacityInternal called 196 nums.
220 | Method name: AbstractStringBuilder.java#newCapacity called 68 nums.
221 | Method name: AccessControlContext.java#calculateFields called 5 nums.
222 | Method name: AccessControlContext.java#combine called 5 nums.
223 | Method name: AccessControlContext.java#optimize called 5 nums.
224 | Method name: AccessController.java#doPrivileged called 37 nums.
225 | Method name: AccessController.java#getContext called 5 nums.
226 | Method name: AccessController.java#getInheritedAccessControlContext called 5 nums.
227 | Method name: AccessController.java#getStackAccessControlContext called 5 nums.
228 | ```
229 |
--------------------------------------------------------------------------------
/src/autorun/jvm/jvmti/antimodule/antimodule.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Odnoklassniki Ltd, Mail.Ru Group
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
18 | #include
19 |
20 | void JNICALL VMInit(jvmtiEnv* jvmti, JNIEnv* env, jthread thread) {
21 | jclass Module = env->FindClass("java/lang/Module");
22 | if (Module == NULL) {
23 | // Seems like pre-module JDK
24 | env->ExceptionClear();
25 | return;
26 | }
27 |
28 | jmethodID getPackages = env->GetMethodID(Module, "getPackages", "()Ljava/util/Set;");
29 |
30 | jmethodID getUnnamedModule = env->GetMethodID(
31 | env->FindClass("java/lang/ClassLoader"), "getUnnamedModule", "()Ljava/lang/Module;");
32 |
33 | jmethodID toString = env->GetMethodID(
34 | env->FindClass("java/lang/Object"), "toString", "()Ljava/lang/String;");
35 |
36 | // Get unnamed module of the current thread's ClassLoader
37 | jvmtiThreadInfo thread_info;
38 | jvmti->GetThreadInfo(NULL, &thread_info);
39 |
40 | jobject unnamed_module = env->CallObjectMethod(thread_info.context_class_loader, getUnnamedModule);
41 |
42 | jint module_count = 0;
43 | jobject* modules = NULL;
44 | jvmti->GetAllModules(&module_count, &modules);
45 |
46 | // Scan all loaded modules
47 | for (int i = 0; i < module_count; i++) {
48 | jvmti->AddModuleReads(modules[i], unnamed_module);
49 |
50 | // Get all module packages as one string: "[java.lang, java.io, ...]"
51 | jobject packages = env->CallObjectMethod(modules[i], getPackages);
52 | jstring str = (jstring) env->CallObjectMethod(packages, toString);
53 |
54 | char* c_str = (char*) env->GetStringUTFChars(str, NULL);
55 | if (c_str == NULL) continue;
56 |
57 | // Export and open every package to the unnamed module
58 | char* package = strtok(c_str + 1, ", ]");
59 | while (package != NULL) {
60 | jvmti->AddModuleExports(modules[i], package, unnamed_module);
61 | jvmti->AddModuleOpens(modules[i], package, unnamed_module);
62 | package = strtok(NULL, ", ]");
63 | }
64 |
65 | env->ReleaseStringUTFChars(str, c_str);
66 | }
67 |
68 | jvmti->Deallocate((unsigned char*) modules);
69 | }
70 |
71 | JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
72 | jvmtiEnv* jvmti;
73 | vm->GetEnv((void**) &jvmti, JVMTI_VERSION_1_0);
74 |
75 | jvmtiEventCallbacks callbacks = {0};
76 | callbacks.VMInit = VMInit;
77 | jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
78 | jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL);
79 |
80 | return 0;
81 | }
82 |
--------------------------------------------------------------------------------
/src/autorun/jvm/jvmti/faketime/faketime.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Odnoklassniki Ltd, Mail.Ru Group
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
18 | #include
19 | #include
20 | #include
21 |
22 | static jlong (*real_time_millis)(JNIEnv*, jclass) = NULL;
23 | static jlong (*real_nano_time_adjustment)(JNIEnv*, jclass, jlong) = NULL;
24 | static jlong offset_millis = 0;
25 |
26 | jlong JNICALL fake_time_millis(JNIEnv* env, jclass cls) {
27 | return real_time_millis(env, cls) + offset_millis;
28 | }
29 |
30 | jlong JNICALL fake_nano_time_adjustment(JNIEnv* env, jclass cls, jlong offset_seconds) {
31 | return real_nano_time_adjustment(env, cls, offset_seconds) + offset_millis * 1000000;
32 | }
33 |
34 | void JNICALL NativeMethodBind(jvmtiEnv* jvmti, JNIEnv* env, jthread thread, jmethodID method,
35 | void* address, void** new_address_ptr) {
36 | char* name;
37 | if (jvmti->GetMethodName(method, &name, NULL, NULL) == 0) {
38 | if (real_time_millis == NULL && strcmp(name, "currentTimeMillis") == 0) {
39 | real_time_millis = (jlong (*)(JNIEnv*, jclass)) address;
40 | *new_address_ptr = (void*) fake_time_millis;
41 | } else if (real_nano_time_adjustment == NULL && strcmp(name, "getNanoTimeAdjustment") == 0) {
42 | real_nano_time_adjustment = (jlong (*)(JNIEnv*, jclass, jlong)) address;
43 | *new_address_ptr = (void*) fake_nano_time_adjustment;
44 | }
45 | jvmti->Deallocate((unsigned char*) name);
46 | }
47 | }
48 |
49 | JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
50 | if (options != NULL) {
51 | if (options[0] == '+' || options[0] == '-') {
52 | offset_millis = atoll(options); // time offset
53 | } else {
54 | offset_millis = atoll(options) - time(NULL) * 1000LL; // absolute time
55 | }
56 | }
57 |
58 | jvmtiEnv* jvmti;
59 | vm->GetEnv((void**) &jvmti, JVMTI_VERSION_1_0);
60 |
61 | jvmtiCapabilities capabilities = {0};
62 | capabilities.can_generate_native_method_bind_events = 1;
63 | #if JNI_VERSION_9
64 | jvmtiCapabilities potential_capabilities;
65 | jvmti->GetPotentialCapabilities(&potential_capabilities);
66 | capabilities.can_generate_early_vmstart = potential_capabilities.can_generate_early_vmstart;
67 | #endif
68 | jvmti->AddCapabilities(&capabilities);
69 |
70 | jvmtiEventCallbacks callbacks = {0};
71 | callbacks.NativeMethodBind = NativeMethodBind;
72 | jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
73 |
74 | jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_NATIVE_METHOD_BIND, NULL);
75 |
76 | return 0;
77 | }
78 |
--------------------------------------------------------------------------------
/src/autorun/jvm/jvmti/heapsampler/heapsampler.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Odnoklassniki Ltd, Mail.Ru Group
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
18 | #include
19 | #include
20 | #include