项目作者: majianzheng

项目描述 :
A powerful Java process starter that manage monitor and debug a series of Java instance online.
高级语言: Java
项目地址: git://github.com/majianzheng/jarboot.git
创建时间: 2019-12-15T04:35:56Z
项目社区:https://github.com/majianzheng/jarboot

开源协议:Apache License 2.0

下载


Jarboot ❤️

logo

CodeQL
Maven Central
Build Status
codecov
GitHub
Average time to resolve an issue
Percentage of issues still open
语雀
Docker Pulls

Jarboot is a platform for Java process startup, shutdown, management and diagnosis. It can manage, guard, monitor and diagnose local and remote Java processes.

In the test environment and daily built integrated environment, a series of jar files such as compilation output can be put into the agreed directory. Jarboot provides a friendly browser UI interface and HTTP interface to manage its start, stop and status monitoring, and execute commands to debug the target process.

中文说明/Chinese Documentation

📚 Document: https://www.yuque.com/jarboot

🍏 Best practices 🔥 : Jarboot with Spring Cloud Alibaba Example ⭐️

🐳 Extensible: Support both JDK SPI and Spring SPI, support plugins develop.

📦 Installation package Download: https://gitee.com/majz0908/jarboot/releases

📺 视频演示: 哔哩哔哩视频

overview

Background and objectives

Jarboot uses Java agent and ASM technology to inject code into the target java process,
which is non-invasive. The injected code is only used for command interaction with jarboot’s service. Some commands
modify the bytecode of the class for class enhancement. A command system similar to Arthas is added, such
as acquiring JVM information, monitoring thread status, acquiring thread stack information, etc.

  • 🌈 Browser interface management, one click start, stop, do not have to manually execute one by one.
  • 🔥 Support start and stop priority configuration[1], and default parallel start.
  • ⭐ Process daemon. If the service exits abnormally after opening, it will be automatically started and notified.
  • ☀️ Support file update monitoring, and restart automatically if jar file is updated after opening.[2]
  • 🚀 Debug command execution, remote debugging multiple Java processes at the same time, the interface is more friendly.
  • 💎 Support user-define command by SPI, support develop plugins.

online diagnose

Architecture brief introduction

Detailed architecture design view

Front-end interface adopts Vue3 technology. The back-end service is mainly implemented by SpringBoot, which provides HTTP interface and static resource broker. The process information is pushed through websocket to the front-end interface in real time, and a long connection is maintained with the started java process to monitor its status.

Chrome >=87
Firefox >=78
Safari >=14
Edge >=88

Install or build

Download the zip package to install or using docker.

Use docker

  1. # Docker image build
  2. mvn clean install -P prod
  3. sh build/docker-push.sh
  4. # Start container
  5. sudo docker run -itd --name jarboot -p 9899:9899 mazheng0908/jarboot

Code build method

Ignore this when using zip package or docker.

Build the jarboot code.

  1. #At first prepare JDK17+ and nodeJs16+, then
  2. $ mvn clean install -P prod

Start jarboot server

Ignore this when using docker.

  1. #Execute startup.sh to start, use startup.cmd when in windows OS.
  2. $ sh startup.sh

Browser access http://127.0.0.1:9899

Enter the login page. Initial username: jarboot, default password: jarboot

SPI Extension, support both JDK and Spring SPI

Use SPI extension can implement your own command, define a command how to execute. And,also can notify stated event to Jarboot server
, don’t need to wait no console time.

SpringBoot Application

  1. Import spring-boot-starter-jarboot dependency
    1. <dependency>
    2. <groupId>io.github.majianzheng</groupId>
    3. <artifactId>spring-boot-starter-jarboot</artifactId>
    4. <version>${jarboot.version}</version>
    5. </dependency>
  2. Implement CommandProcessorSPI interface

Also, you can use @Bean in the method.

It will use bean name as the command name if not annotated by @Name.

  1. @Name("spring.command.name")
  2. @Summary("The command summary")
  3. @Description("The command usage detail")
  4. @Component
  5. public class DemoServiceImpl implements DemoService, CommandProcessor {
  6. @Override
  7. public String process(CommandSession session, String[] args) {
  8. return "Spring boot Demo user-defined command using Spring SPI";
  9. }
  10. //implement other method...
  11. }

It will add two new spring debug command spring.bean and spring.env after imported
spring-boot-starter-jarboot dependence.

  1. #spring.bean usage:
  2. $ spring.bean [-b <name>] [-d]
  3. #Examples:
  4. # Get all bean names
  5. $ spring.bean
  6. # Get bean info
  7. $ spring.bean -b beanName
  8. # Get bean detail definition
  9. $ spring.bean -b beanName -d
  10. #sping.env usage:
  11. $ spring.env <name>
  12. #Examples:
  13. $ spring.env spring.application.name

None SpringBoot Application

Demonstrate how to use ordinary non springboot applications.

How to create user-defined command

  1. Import jarboot api dependency
    1. <dependency>
    2. <groupId>io.github.majianzheng</groupId>
    3. <artifactId>jarboot-api</artifactId>
    4. <scope>provided</scope>
    5. <version>${jarboot.version}</version>
    6. </dependency>
  2. Implement spi interface
    1. /**
    2. * Use Name to define the command name
    3. */
    4. @Name("demo")
    5. @Summary("The command summary")
    6. @Description("The command usage detail")
    7. public class DemoCommandProcessor implements CommandProcessor {
    8. @Override
    9. public String process(CommandSession session, String[] args) {
    10. return "demo SPI command result.";
    11. }
    12. }
  3. Create spi define file

Then create a file in resources/META-INF/services named
spi.cmd.io.github.majianzheng.jarboot.api.CommandProcessor the content is class full name.

Proactive notification of startup completion

  1. public class DemoApplication {
  2. public static void main(String[] args) {
  3. // do something
  4. try {
  5. //Notify completion
  6. JarbootFactory.createAgentService().setStarted();
  7. } catch (Exception e) {
  8. log(e.getMessage());
  9. }
  10. }
  11. }

Tools

File browse

file_browse

Terminal

terminal

Command list

bytes

View the class bytes,Usage:

  1. jarboot$ bytes io.github.majianzheng.jarboot.demo.DemoServerApplication
  2. ClassLoader: org.springframework.boot.loader.LaunchedURLClassLoader@31221be2
  3. ------
  4. getUser
  5. L0
  6. LINENUMBER 27 L0
  7. ...
  8. ILOAD 1
  9. ILOAD 2
  10. IADD
  11. IRETURN
  12. L8

stdout

Turn on or off real-time display of standard output stream (initially on), it will be displayed on the front-end UI of
the web in real time. The output stream includes System.out.println, System.err.println and
log printing information such as logger.info(“hello”) in the code.

Note: The implementation mechanism of this function has been carefully designed. It is recommended to be turned on all
the time, which has no impact on performance and can be accelerated when starting.

  1. #Turn on real time display of standard output stream
  2. jarboot$ stdout on
  3. #Turn off real time display of standard output stream
  4. jarboot$ stdout off
  5. #Get current status on or off
  6. jarboot$ stdout

dashboard

This is the real time statistics dashboard for the current system,click x cancel.

dashboard

jad

Decompile the specified classes.

  1. jarboot$ jad [-c] java.lang.String
  2. `

jad

jvm

Check the current JVM’s info

  1. jarboot$ jvm
  2. `

sc

Search any loaded class with detailed information.

  1. $ sc -d org.springframework.web.context.support.XmlWebApplicationContext
  2. class-info org.springframework.web.context.support.XmlWebApplicationContext
  3. code-source /Users/xxx/work/test/WEB-INF/lib/spring-web-3.2.11.RELEASE.jar
  4. name org.springframework.web.context.support.XmlWebApplicationContext
  5. isInterface false
  6. isAnnotation false
  7. isEnum false
  8. isAnonymousClass false
  9. isArray false
  10. isLocalClass false
  11. isMemberClass false
  12. isPrimitive false
  13. isSynthetic false
  14. simple-name XmlWebApplicationContext
  15. modifier public
  16. annotation
  17. interfaces
  18. super-class +-org.springframework.web.context.support.AbstractRefreshableWebApplicationContext
  19. +-org.springframework.context.support.AbstractRefreshableConfigApplicationContext
  20. +-org.springframework.context.support.AbstractRefreshableApplicationContext
  21. +-org.springframework.context.support.AbstractApplicationContext
  22. +-org.springframework.core.io.DefaultResourceLoader
  23. +-java.lang.Object
  24. class-loader +-org.apache.catalina.loader.ParallelWebappClassLoader
  25. +-java.net.URLClassLoader@6108b2d7
  26. +-sun.misc.Launcher$AppClassLoader@18b4aac2
  27. +-sun.misc.Launcher$ExtClassLoader@1ddf84b8
  28. classLoaderHash 25131501
  29. `

trace

method calling path, and output the time cost for each node in the path.

  1. jarboot$ trace io.github.majianzheng.jarboot.demo.DemoServerApplication add
  2. Affect(class count: 2 , method count: 1) cost in 63 ms, listenerId: 2
  3. `---ts=2021-06-15 23:34:20;thread_name=http-nio-9900-exec-3;id=13;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@4690b489
  4. `---[0.053485ms] io.github.majianzheng.jarboot.demo.DemoServerApplication:add()

watch

methods in data aspect including return values, exceptions and parameters

Watch the first parameter and thrown exception of io.github.majianzheng.jarboot.demo.DemoServerApplicatio#add only if it throws exception.

  1. jarboot$ watch io.github.majianzheng.jarboot.demo.DemoServerApplicatio add {params[0], throwExp} -e
  2. Press x to abort.
  3. Affect(class-cnt:1 , method-cnt:1) cost in 65 ms.
  4. ts=2018-09-18 10:26:28;result=@ArrayList[
  5. @RequestFacade[org.apache.catalina.connector.RequestFacade@79f922b2],
  6. @NullPointerException[java.lang.NullPointerException],
  7. ]

thread

Check the basic info and stack trace of the target thread.

  1. jarboot$ thread -n 3
  2. "nioEventLoopGroup-2-1" Id=31 cpuUsage=0.37% deltaTime=0ms time=880ms RUNNABLE
  3. at sun.management.ThreadImpl.dumpThreads0(Native Method)
  4. at sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:448)
  5. at impl.cmd.io.github.majianzheng.jarboot.core.ThreadCommand.processTopBusyThreads(ThreadCommand.java:209)
  6. at impl.cmd.io.github.majianzheng.jarboot.core.ThreadCommand.run(ThreadCommand.java:120)
  7. at basic.io.github.majianzheng.jarboot.core.EnvironmentContext.runCommand(EnvironmentContext.java:162)
  8. at cmd.io.github.majianzheng.jarboot.core.CommandRequestSubscriber.execute(CommandDispatcher.java:35)
  9. at server.io.github.majianzheng.jarboot.core.JarbootBootstrap$1.onText(JarbootBootstrap.java:94)
  10. at io.github.majianzheng.jarboot.core.ws.WebSocketClientHandler.channelRead0(WebSocketClientHandler.java:83)
  11. at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
  12. "C2 CompilerThread1" [Internal] cpuUsage=3.14% deltaTime=6ms time=4599ms
  13. "C2 CompilerThread0" [Internal] cpuUsage=2.28% deltaTime=4ms time=4692ms

Classloader

View the class loader extends tree, url and class loader info.

  1. jarboot$ classloader
  2. name numberOfInstances loadedCountTotal
  3. org.springframework.boot.loader.LaunchedURLClassLoader 1 3929
  4. BootstrapClassLoader 1 2623
  5. io.github.majianzheng.jarboot.agent.JarbootClassLoader 1 1780
  6. sun.misc.Launcher$AppClassLoader 1 59
  7. sun.reflect.DelegatingClassLoader 58 58
  8. sun.misc.Launcher$ExtClassLoader 1 18
  9. Affect(row-cnt:6) cost in 35 ms.

heapdump

dump java heap in hprof binary format, like jmap.

  1. jarboot$ heapdump
  2. `

heap dump

sysprop

Examine the system properties from the target JVM

  1. #Get all.
  2. jarboot$ sysprop
  3. #Get one property.
  4. jarboot$ sysprop user.home

Credit

Projects

  • bytekit Java Bytecode Kit.
  • Arthas Some command is developed on the source of Arthas.

Thanks

We used JetBrains tools for developing and building.

JetBrains Logo (Main) logo

Contact

  • Mail: 282295811@qq.com
  • QQ group: 663881845
  • QQ群已满,微信群二维码会过期,大家关注下抖音吧,关注后加入抖音的粉丝群
  • 抖音号:1077242754

抖音
投喂

仓库镜像


1: You can configure the priority level, starting from the integer value of 1. The more you start first, the reverse is the order of stop.

2: In development, it can be built automatically by tools such as gitlab runner, Jenkins, etc. and copied to the directory specified by Jarboot through script. Updates monitored by Jarboot will restart the service automatically. Directory monitoring implements anti-shake design (multiple updates within a certain period of time will trigger only one restart).