Wechat official account: BugStack wormhole stack
Precipitation, sharing, growth, focus on original thematic cases, in the most easy to learn programming way to share knowledge, so that themselves and others can gain. Projects completed so far are; Netty4.x practical case, Implementing JVM with Java, Full-link monitoring based on JavaAgent, Handwritten RPC framework, Architectural design case [Ing], etc.
Background description
JVMTI(JVM Tool Interface) is a native programming Interface provided by Java virtual machines, which is located at the bottom of JPDA. JVMTI provides functions such as performance analysis, debugging, memory management, and thread analysis.
JPDA defines a complete and independent system, which consists of three relatively independent levels, and defines the way they interact with each other, or defines the interface through which they communicate. The three layers are Java Virtual Machine Tool Interface (JVMTI), Java Debug Line Protocol (JDWP), and Java Debug Interface (JDI). These three modules break down the debugging process into several natural concepts: the debugger and the debuggee, and the communicator between them. The debugger runs on the Java VIRTUAL machine we want to debug. It can monitor the information of the current VIRTUAL machine through the standard interface JVMTI. The debugger defines debugging interfaces that can be used by users. Through these interfaces, users can send debugging commands to the vm to be debugged, and the debugger receives and displays the debugging results. Between the debugger and the debugger, debugging commands and debugging results are transmitted through the JDWP communication protocol. All commands are encapsulated into JDWP command packages and sent to the debugger through the transport layer. After receiving the JDWP command packages, the debugger parses the commands and converts them into JVMTI calls to run on the debugger. Similarly, the results of a JVMTI run are formatted as JDWP packets, sent to the debugger and returned to the JDI call. Debugger developers get data and issue instructions through JDI.
The module | level | A programming language | role |
---|---|---|---|
JVMTI | The underlying | C | Obtain and control the current VM status |
JDWP | A mediation layer | C | Define the data format for JVMTI and JDI interactions |
JDI | At the top | Java | Provides a Java API to remotely control the virtual machine being debugged |
Java Virtual Machine Tool Interface (JVMTI) is the Java Virtual Machine Tool Interface (JVMTI), which is a set of native interfaces directly provided by Virtual machines and is at the bottom of the whole JPDA system. All debugging capabilities are essentially provided through JVMTI. Through these interfaces, developers can not only debug Java programs running on the virtual machine, but also view their running status, set callback functions, and control certain environment variables to optimize program performance. As we know, JVMTI is the predecessor of JVMDI and JVMPI, which were originally used to provide the functions of debugging Java programs and tuning Performance of Java programs respectively. JVMDI and JVMPI were replaced by the JDK after J2SE 5.0, JVMDI was not supported in the latest Java SE 6, and JVMPI is scheduled to be completely replaced after Java SE 7.
Java Debug Wire Protocol (JDWP) Java Debug Wire Protocol (JDWP) is a communication and interaction Protocol designed for Java debugging. It defines the format of information transmitted between the debugger and the program being debugged. In JPDA system, the format of the interactive data between the front-end debugger process and the back-end debuggee process is described by JDWP. It defines the request command, response data and error code in detail, and ensures the smooth communication between front-end and back-end JVMTI and JDI. For example, in the implementation provided by Sun, it provides a dynamic link library file named JDMP. DLL (JDMP. so). This dynamic library file implements an Agent that parses requests or commands from the front end and converts them into JVMTI calls. The return value of the JVMTI function is then encapsulated as JDWP data and sent back to the back end.
Java Debug Interface (JDI) The Java Debug Interface (JDI) is the highest level of the three modules and is implemented by the Java language in most JDKS. JDI consists of an interface defined for the front end, through which debugging tool developers can remotely control the running of the debugger on the back end virtual machine through the debugger on the front end virtual machine. JDI can not only help developers format JDWP data, but also provide optimization services such as queues and caching for JDWP data transmission. In theory, developers can support remote debugging across platforms using only JDWP and JVMTI, but writing JDWP programs directly is time-consuming and inefficient. Therefore, the introduction of JDI layer based on Java simplifies the operation and improves the efficiency of developers to develop debugging programs.
The development of a brief introduction
Based on the interface service provided by jvmti, using C++ code (win32-add_library) to develop monitoring service in Agent_OnLoad, and generate DLL files. After development, add agentPath to your Java code so that you can monitor the information content you need.
Environment to prepare
- Dev-C++
- JetBrains CLion 2018.2.3
- IntelliJ IDEA Community Edition 2018.3.1×64
- Jdk1.8 64
- Jvmti (in JDK installation directory jdk1.8.0_45\include, copy to the same level of directory as the project case)
Configuration information (path related modified to own)
- C++ development tool Clion configuration
- Configuration position; Settings->Build,Execution,Deployment->Toolchains
- MinGM configuration: D: Program Files (x86)\ dev-cpp \MinGW64
- Configured during Java debugging
- Run/Debug Configurations ->VM Options
- – AgentPath: e :\ itStack\ \ itStack.org \demo\jvmti\itstack-demo- jVMti-dll \cmake-build-debug\ libitStack_demo_jVMti_dl.dll
Code sample
C++ code block:
#include <iostream>
#include <cstring>
#include "jvmti.h"using namespace std; Static void JNICALL callbackException(jvmtiEnv *jvmti_env, JNIEnv *env, jthread THR, jmethodID methodId, Jlocation, jobject exception, jmethodID catch_method, jlocation catch_location) { jvmti_env->GetMethodDeclaringClass(methodId, &clazz); Char *class_signature; jvmti_env->GetClassSignature(clazz, &class_signature, nullptr); String ::size_type IDx; string class_signature_str = class_signature; idx = class_signature_str.find("org/itstack");
if(idx ! = 1) {return; } // Exception class name char *exception_class_name; jclass exception_class = env->GetObjectClass(exception); jvmti_env->GetClassSignature(exception_class, &exception_class_name, nullptr); Char *method_name_ptr, *method_signature_ptr; jvmti_env->GetMethodName(methodId, &method_name_ptr, &method_signature_ptr, nullptr); Jlocation start_location_ptr; // The start position of the method jlocation end_location_ptr; Jvmti_env ->GetMethodLocation(methodId, &start_location_ptr, &end_location_ptr); Cout <<"Test Results-Location class signature:" << class_signature << endl;
cout << "Test Results-Location method information:" << method_name_ptr << "- >" << method_signature_ptr << endl;
cout << "Test Results-Location method Location:" << start_location_ptr << "- >" << end_location_ptr + 1 << endl;
cout << "Test Results - Name of exception class:" << exception_class_name << endl;
cout << "Test result-output exception information (line number can be parsed) :" << endl;
jclass throwable_class = (*env).FindClass("java/lang/Throwable");
jmethodID print_method = (*env).GetMethodID(throwable_class, "printStackTrace"."()V"); (*env).CallVoidMethod(exception, print_method); } JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { jvmtiEnv *gb_jvmti = nullptr; // Initialize the VM ->GetEnv(reinterpret_cast<void **>(&gb_jvmti), JVMTI_VERSION_1_0); // Create a new environment jvmticapCaps; memset(&caps, 0, sizeof(caps)); caps.can_signal_thread = 1; caps.can_get_owned_monitor_info = 1; caps.can_generate_method_entry_events = 1; caps.can_generate_exception_events = 1; caps.can_generate_vm_object_alloc_events = 1; caps.can_tag_objects = 1; Gb_jvmti ->AddCapabilities(& CAPS); // Create a new callback function jvmtiEventCallbacks callbacks; memset(&callbacks, 0, sizeof(callbacks)); Callback. Exception = &callbackException; // set the callback function gb_jVMti ->SetEventCallbacks(&callbacks, sizeof(callbacks)); // Enable event listener (JVMTI_EVENT_EXCEPTION) gb_jVMti ->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_EXCEPTION, nullptr);return JNI_OK;
}
JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm) {
}
Copy the code
Java code block:
package org.itstack.demo.jvmti;
import java.util.logging.Logger;
public class TestLocationException {
public static void main(String[] args) {
Logger logger = Logger.getLogger("TestLocationException");
try {
User resource = new User();
Object obj = resource.queryUserInfoById(null);
logger.info("Test Results:"+ obj); } catch (Exception e) {}} class User {Logger Logger = logger.getLogger ("User");
public Object queryUserInfoById(String userId) {
logger.info("Get user information based on user Id" + userId);
if (null == userId) {
throw new NullPointerException("Null pointer error in obtaining user information based on user Id");
}
returnuserId; }}Copy the code
The test results
On April 13, 2019 afternoon 12:21:45 org. Itstack. Demo. Jvmti. User queryUserInfoById information: According to the User Id for the User information null test results - orientation class signature: Lorg/itstack/demo/jvmti/User; Test result - Location method information: queryUserInfoById -> (Ljava/lang/String) Ljava/lang/Object; Test result - locating methods location: 0 - > test results - the name of the exception class: 43 Ljava/lang/NullPointerException. Can be analyzed and the abnormal test results and output information (line number) : Java. Lang. NullPointerException: Get user information based on the user Id, Null pointer exception at org. Itstack. Demo. Jvmti. User. QueryUserInfoById ats (TestLocationException. Java: 23) org.itstack.demo.jvmti.TestLocationException.main(TestLocationException.java:10)Copy the code
Other content:
- jvmti api
- JPDA system Overview