如何在JDK 17应用中识别通过JNI调用的本地库?
在JDK 17中识别JNI调用的本地库方法
已确认Java应用存在原生代码内存泄漏,且问题不在应用自身Java代码中,需要排查依赖的本地库。早期依赖反射访问ClassLoader.loadedLibraryNames的方式在JDK 17中已失效,以下是JDK 17可用的合规方案:
1. 使用Runtime类的loadedLibraries()方法(JDK 9+)
JDK 9引入了Runtime.loadedLibraries()方法,可直接获取所有已加载的本地库路径,无需反射,完全符合JDK模块化规范。代码示例:
import java.lang.Runtime; public class NativeLibChecker { public static void main(String[] args) { Runtime.getRuntime().loadedLibraries().forEach(System.out::println); } }
执行后会输出所有已加载本地库的绝对路径,方便定位可疑依赖。
2. 通过JVM启动参数打印加载详情
启动应用时添加以下参数之一,JVM会在控制台输出本地库的加载信息:
XX:+PrintLibraryLoadingDetails:输出详细的库加载日志,包括加载的路径、时间及关联类-XX:+PrintSharedSpaces:输出共享库(包括本地库)的加载情况
无需修改代码,适合快速排查场景。
3. 使用JDK工具jcmd离线排查
通过jps命令获取应用进程ID后,执行以下命令:
jcmd <你的应用PID> VM.native_libraries
该命令会输出进程中所有已加载本地库的详细信息,包括库路径、加载状态、内存映射地址等,是生产环境离线排查的常用手段。
4. 自定义ClassLoader追踪加载行为
如果应用使用自定义ClassLoader加载本地库,可以重写findLibrary方法来记录加载的库信息:
public class TrackingClassLoader extends ClassLoader { @Override protected String findLibrary(String libname) { String libPath = super.findLibrary(libname); if (libPath != null) { System.out.printf("ClassLoader加载本地库:%s,路径:%s%n", libname, libPath); } return libPath; } }
这种方式适合追踪特定ClassLoader加载的本地库,需要结合应用的类加载逻辑使用。
内容的提问来源于stack exchange,提问作者Augustin Cayot
相关产品推荐
相关产品推荐

