This is the seventh day of my participation in the More text Challenge. For details, see more text Challenge
Java non-stop monitoring & hot operation
The introduction
While using Arthas, I found that some functions worked well, but the command line was difficult to use. With a learning attitude, I designed my own application with no downtime, burying, hotfix, monitoring, etc., and provided a WEB page for operation, and continued to integrate some commonly used functions.
1. Supported operations
- Monitors market information such as JVM, GC, startup parameters, threads, and system parameters
- For a running program, code is dynamically woven into a method to obtain the execution time of a function
- For a running program, dynamically weave code into a method to get a controller method request parameter and return value
- For running programs, get the percentage of CPU time occupied by all threads and support for viewing the stack information that a given thread is running
- Hot fix: decompile the exported Java file, modify it, and then import it. Hot compile it by reloading it with classLoad.
- Because you are using web page operations, the IP address needs to be changed to the target process machine IP (default is localhost, do not change if running locally).
The key technology
Technical name | role |
---|---|
Javaagent | Loading the bytecode before it is run, or manipulating it while it is running |
VirtualMachine | Attach to the target process at run time and invoke the Agent |
architecture
engineering | technology |
---|---|
web | Vue + Ant design |
server | Springboot+Websocket(hereafter deprecated to NettyServer) |
agent | netty + Javassist + cfr + JavaCompiler |
2. How to install and use it?
- Go to Ali Cloud Maven warehouse to download Jar package
(Maven defaults to foreign repositories)
(Ali Cloud Maven warehouse) recommended to use!
Making the source code
Search nobugboy or ETrace
Get the download address, he will dynamically refresh this link, so you need to search and download.
- After the connection is obtained
1. Win directly click to download, MAC/Linux wget connection 2. Rename the file ETrace-1.2.4.jarCopy the code
- run
Linux/MacOS is defined by the name of the environment variable that you configure as the value, $JAVA_HOME Windows $JAVA_HOME directly replace the javaHome absolute directory Java -jar -xBootCLASspath /a:$JAVA_HOME/lib/tools.jar ETrace - 1. The jarCopy the code
- Default user name admin Password admin123
3. GIF demonstration operation
- To demonstrate the CPU and thread tracing, click the thread directly to get the current stack information (locate the high CPU cause)
- Demo weaving print execution time (I slept for 1s for good look)
- Demonstrates weaving in return values for print parameters
4. Hot fix, this function is too cumbersome to record, directly graphic bar
Scenario: A classmate submits code with null pointer exception to the production environment, which is not covered by the test.
@getMapping (value = "/get/{id}",name = "getuser ") public User test(@pathVariable (value = "id",name = "id") String id){ User user = null; User. Elegantly-named setName (" test "); return user; }}}}}}}}}}}} exception is java.lang.NullPointerException at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~ [spring - webmvc - 5.3.6. Jar: 5.3.6] at org. Springframework. Web. Servlet. FrameworkServlet. DoGet (FrameworkServlet. Java: 898) ~ [spring - webmvc - 5.3.6. Jar: 5.3.6]Copy the code
At this point, the service is already running. If we cannot restart the service, we will fix it. First, find the class path that needs to be modified and output it to the desktop (make sure to add/at the end of the output path).
Modify the null pointer problem, edit the exported file
/* * Decompiled with CFR. * * Could not load the following classes: * com.example.springboottestdemo.controller.User */ package com.example.springboottestdemo.controller; import com.example.springboottestdemo.controller.User; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController(value="\u7528\u6237\u76f8\u5173\u63a5\u53e3") public class TestController { @GetMapping(value={"/last"}, name="get\u8bf7\u6c42\u6d4b\u8bd5\u53c2\u6570\u63cf\u8ff0") public User test2(User user) { return user; } @PostMapping(value={"/post"}, name="post\u8bf7\u6c42\u6d4b\u8bd5\u53c2\u6570\u63cf\u8ff0") public User test1(@RequestBody User user) { System.out.println((Object)user); return user; } @GetMapping(value={"/get/{id}"}, name="\u6839\u636eid\u83b7\u53d6\u7528\u6237") public User test(@PathVariable(value="id", Name ="id") String id) {// fix User here. User = new User(); user.setName("\u6d4b\u8bd5"); return user; }}Copy the code
When you see “Compiler OK” on the console, you are ready to load it again
“Re-successful!” “Load” indicates that the load succeeded. At this point, we request the interface that reported the error again.
The curl localhost: 8080 / get / 1 {" id ", null, "name" : "test", "us", null, "type" : null} %Copy the code