如何检查Java进程中是否加载了类

时间:2019-04-17 09:47:27

标签: java linux spring-boot

我的任务是找出Linux系统上正在运行多少springboot应用程序。 所以我计划要做的是,

1。以获得所有Java进程ID

$ ps -aux|grep java

2。。然后以某种方式从ID中获取已加载的类。

我不知道是否可能。有人请好心引导我正确的方向吗? P.S。:我正在使用Java在Process类的帮助下运行上述命令,如下所示:

Process process = Runtime.getRuntime().exec("ps -ef");

所以我想从一个Java项目中做到这一点。

4 个答案:

答案 0 :(得分:0)

  1. 您需要在应用程序的启动命令行中添加某种标识符。例如。像这样:

    String id = "com.app.demo";
    
  2. 运行应用程序时,请确保包含字符串。假设您是从Java内部启动的,请执行以下操作:

    Runtime.getRuntime().exec("C:\...\javaw.exe -cp ... -Dwhatever=" + id + " com.app.app.demo.Main");
    
  3. 通过id$ps aux | grep -i com.app.app.demo一样获得应用程序。在Java中调用Runtime.getRuntime().exec("ps aux | grep -i com.app.app.demo");

我宁愿改用ProcessBuilder(来自Java 8),并通过bash运行命令:

Process process = new ProcessBuilder().command("bash", "ps aux | grep com.app.app.demo").start()

希望这给出了一个主意。

答案 1 :(得分:0)

快速而肮脏的方法:在您的类中添加一些静态块,并在其中将某些内容打印到日志(或system.out)中。静态块是在类加载器加载类时执行的,而不是在实例化第一个实例时执行的(这是首次调用构造函数时)。然后,如果您的打印输出在日志中,则该类已加载。示例:
public class Sample { private static final Logger logger = ... static { logger.info("class Sample is loaded"); } ... }

答案 2 :(得分:0)

假设您可以确定一些特定的类来确定应用程序是否是springboot应用程序,则可以使用jdk中的某些工具,该工具可以输出已加载的类。我已经用jcmd尝试过了(您可以在jre / bin /下找到它):

我对bash不太满意,因此效率可能不是很高,但是这对我有用,假设每个springboot应用程序都加载了类org.springframework.boot.logging.LoggingInitializationContext并且没有非springboot应用程序加载了它。

ps aux | grep [j]ava | awk '{print $2}' | xargs -I{} jcmd {} VM.class_hierarchy | grep "org.springframework.boot.logging.LoggingInitializationContext"

它将查找包含java的进程,仅获取PID,然后将其传递给jcmd,在其中您为特定类进行grep。输出似乎是正确的,唯一的问题是我在此长管道中松开了PID,但不确定如何打印。 但是,如果您的问题是“有多少springboot应用程序”,则可能不是问题。我也不确定在使用jcmd VM.class_hierarchy时类是否会出现两次,但是看起来却不一样。

注意:这在JDK 11上有效。我首先尝试了jmap,但是由于某种原因在我的JDK 11上不起作用。

答案 3 :(得分:0)

我来到此页面是为了寻找“如何查找 jar 是否已加载”的食谱(这与原始问题有点不同)。但也许它对某人有用:

我发现 jcmd 是获取此信息的最佳方式,例如:

  1. 我有一个 PID 为 1 的正在运行的 JVM(它是一个在 K8s 中启动的 CN 应用程序):
$ jps 
1 MyAppLauncher
529 Jps
  1. 找出 jcmd 为这个 JVM 提供的选项:
[eceuser@ecs1-0 temp]$ jcmd 1 help
1:
The following commands are available:
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
VM.check_commercial_features
VM.unlock_commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
VM.classloader_stats
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.finalizer_info
GC.heap_info
GC.run_finalization
GC.run
VM.uptime
VM.dynlibs
VM.flags
VM.system_properties
VM.command_line
VM.version
help
  1. 经过一些尝试和错误,我发现 VM.dynlibs 可以满足我的需求:
$ jcmd 1 VM.dynlibs | grep custom
7f59a4b3b000-7f59a4b3d000 r--s 00000000 fd:00 1116085962                 /home/app/lib/custom-fi-extensions-0.0.1-SNAPSHOT.jar

是的,这个 jar 已经加载了。