美文网首页
无法动态附加到 Java 进程?

无法动态附加到 Java 进程?

作者: AlphaHinex | 来源:发表于2021-12-19 12:18 被阅读0次

原文地址:https://alphahinex.github.io/2021/12/19/unable-to-open-socket-file/

cover

description: "导致 jmap、jstack 等命令无法正常使用"
date: 2021.12.19 10:34
categories:
- Java
tags: [Java, JDK]
keywords: socket file, .java_pid, java.io.tmpdir, Dynamic Attach, /tmp, systemd


现象

找出 Java 应用频繁 Full GC 的原因 中介绍了一些 JDK 中自带的命令,
如:jmapjstat 等,但在实际使用时,可能会遇到类似如下的问题:

$ jmap -histo 2867
2867: Unable to open socket file: target process not responding or HotSpot VM not loaded
The -F option can be used when the target process is not responding

出现这种情况时,如果不是 Java 进程所属的用户和执行命令的用户不一致导致,那么按照提示使用 -F 参数可能也无济于事,重启 Java 应用后才可正常使用。

原因

出现这种情况时,基本是 socket file(.java_pid<pid> 文件)被删除导致,其中 <pid> 为对应 Java 进程的 ID。

这个文件在哪?

这个文件,会被生成到操作系统临时路径下,如 linux 下为 /tmp

默认情况下,可以通过 System.getproperty("java.io.tmpdir")(Java 应用的临时路径)来获取操作系统临时路径,但 java.io.tmpdir 这个属性可以通过环境变量、启动参数等进行改变,而操作系统的临时路径是没有办法被修改的,因为是硬编码到 对应操作系统的 JVM 代码 中的,如:

// This must be hard coded because it's the system's temporary
// directory not the java application's temp directory, ala java.io.tmpdir.
const char* os::get_temp_directory() { return "/tmp"; }

以现象中的 pid(2867)为例,对应 Linux 操作系统下该 Java 进程的 socket file 全路径为:/tmp/.java_pid2867

为什么需要这个文件?

这是由 JVM 的 Dynamic Attach 机制 决定的。

jmapjstack 等命令,都是通过这个机制来实现的。该机制的作用是,在 Java 进程运行过程中,为其动态附加一个外部进程,使外部进程可以与 Java 进程进行通信,实现例如 dump 等交互。

jmap -histojmap -dumpjstack 等命令执行时,都需要指定一个 Java 进程的 PID,作用即为向目标 JVM 发送一个 attach 请求。

通过 Java 代码,也可以发起这个附加请求,如:

import com.sun.tools.attach.VirtualMachine;

...

String pid = "2867";
VirtualMachine jvm = VirtualMachine.attach(pid);
...
jvm.detach();

...

在第一次发生附加请求时,Dynamic attach 会在目标 JVM 中运行一个 Attach Listener 线程,可通过如下方式观察:

# 前台运行一个 java 应用,观察 console 输出内容
$ java -jar hello.jar

# 新开一个终端窗口,获得 java 进程 id
$ jps
22480 jar
23032 Jps

# 发送一个 QUIT 信号
$ kill -3 22480

此时会在 Java 应用的 console 中,输出线程相关信息。在未进行过 Dynamic attach 时,Java 应用的线程栈中是没有 Attach Listener 线程的。

# 触发一个附加请求
$ jstack -l 22480
...
"Attach Listener" #20 daemon prio=9 os_prio=31 tid=0x00007fd113814000 nid=0x450b waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None
...

可以看到线程栈中多出了一个名为 Attach Listener 的线程。

随后,这个线程会与发起附加请求的源 JVM,以依赖操作系统的方式进行通信:

* On Solaris, the Doors IPC mechanism is used. The door is attached to a file in the file system so that clients can access it.
* On Linux, a Unix domain socket is used. This socket is bound to a file in the filesystem so that clients can access it.
* On Windows, the created thread is given the name of a pipe which is served by the client. The result of the operations are written to this pipe by the target JVM.

在 Linux 中,上面文档所指的 This socket is bound to a file in the filesystem,即为前面提到的 .java_pid<pid> 文件。

这个文件为什么会被删除?

因为这个 socket file 生成在操作系统的临时路径,如 Linux 下的 /tmp,而 Linux 的 /tmp 路径下的文件,默认在重启,或者超过 10 天的情况下会被删除。

能不能让这个文件生成到别的路径?

如上所述,操作系统的临时路径是在 JVM 源代码中硬编码的,并且与 java.io.tmpdir 等属性不同,无法通过环境变量等形式进行更改。

解决方案

分析完原因,让这个问题不再发生的解决方案,就只剩下让这个生成在操作系统临时路径下的 socket 文件不被删除了。

以 CentOS7 为例,临时文件夹下文件的删除,是由 Systemd Cleanup 任务完成的,可在其配置文件 /usr/lib/tmpfiles.d/tmp.conf 中,添加如下内容,以排除对 socket 文件的删除:

x /tmp/.java_pid*

其中,x 代表在清理任务中,排除符合的文件。

参考资料

相关文章

  • 无法动态附加到 Java 进程?

    原文地址:https://alphahinex.github.io/2021/12/19/unable-to-op...

  • 容器被无法获取java进程调试

    容器被无法获取java进程调试 今天尝试在容器内使用arthas调试,发现无法attch到java进程,jstac...

  • 03 java并发-小结

    Java 并发基础总结 1.1. 进程 进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。进程...

  • 关于推送接收不到的处理

    小米【MIUI】 自启动管理:需要把应用加到【自启动管理】列表,否则杀进程或重新开机后进程无法开启 通知栏设置:应...

  • Java之多线程

    Java多线程概念 进程(Process):  进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态...

  • How to resolve Maven Project can

    现象 解决 附,将jar添加到本地仓库的方法 添加到本地仓库例子 添加到本地后引入例子

  • 进程

    进程 进程和程序的区别 1)程序是静态概念(是指令的有序集合。“程序文件”) 进程时动态概念(动态产生,动态消亡)...

  • java JVM 调优常用CMD

    Java JVM First查看java进程: ps -ef|grep java jps -l (显示java进程...

  • 梳理笔记

    java中进程和线程实现的方式 进程的三个特点:独立性 动态性 并发性线程特点: 线程可以完成一定任务,可以和其它...

  • 慕课网 - 深入浅出Java多线程

    课程地址:深入浅出Java多线程课程讲师:Arthur 进程 程序(任务)的执行过程 (动态性-当双击运行) 持有...

网友评论

      本文标题:无法动态附加到 Java 进程?

      本文链接:https://www.haomeiwen.com/subject/uxjnfrtx.html