如何使用Java跟踪JVM文件系统访问
Posted Java攻城师
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用Java跟踪JVM文件系统访问相关的知识,希望对你有一定的参考价值。
使用自定义安全管理器作为本机跟踪程序的低开销替代方法。
对于跟踪Java应用程序的文件系统访问,本机跟踪工具始终是首选。在Windows上,使用Process Monitor跟踪I / O。在Linux上,使用strace。其他平台也提供类似的功能。
通过直接在Java中进行跟踪,您可以解决环境限制。例如,在缺少该CAP_SYS_PTRACE功能的容器中strace不可用,并且容器主机并非始终可访问。此外,潜在的更轻量的跟踪机制可方便地在生产环境中进行跟踪。
要走Java路线,您可以通过扩展来实现自己的安全管理器java.lang.SecurityManager。此类提供了checkRead,checkWrite和checkDelete方法,一旦代码尝试进行相应的访问,它们就会被调用。
一个示例实现:
public class TraceSecurityManager extends SecurityManager {
public void checkRead(String file) {
System.out.println("Read: " + file);
super.checkRead(file);
}
public void checkRead(String file, Object context) {
System.out.println("Read: " + file);
super.checkRead(file, context);
}
public void checkWrite(String file) {
System.out.println("Write: " + file);
super.checkWrite(file);
}
public void checkDelete(String file) {
System.out.println("Delete: " + file);
super.checkDelete(file);
}
}
为了测试样本,我们使用Java编译器作为测试对象。为了启用跟踪安全管理器,我们设置适当的系统属性,并使用有效的Java源文件执行命令Test.java:
$ java -Djava.security.manager=TraceSecurityManager com.sun.tools.javac.Main Test.java
Read: /home/user/com/sun/tools/javac/resources/spi/compilerProvider.class
Read: /home/user/com/sun/tools/javac/resources/compiler_en.properties
Read: /home/user/com/sun/tools/javac/resources/compiler_en_US.properties
Exception in thread "main" java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "getenv.JDK_JAVAC_OPTIONS")
at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
at java.base/java.security.AccessController.checkPermission(AccessController.java:897)
at java.base/java.lang.SecurityManager.checkPermission(SecurityManager.java:322)
at java.base/java.lang.System.getenv(System.java:999)
at jdk.compiler/com.sun.tools.javac.main.CommandLine.appendParsedEnvVariables(CommandLine.java:252)
at jdk.compiler/com.sun.tools.javac.main.CommandLine.parse(CommandLine.java:99)
at jdk.compiler/com.sun.tools.javac.main.CommandLine.parse(CommandLine.java:123)
at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:215)
at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:170)
at jdk.compiler/com.sun.tools.javac.Main.compile(Main.java:57)
at jdk.compiler/com.sun.tools.javac.Main.main(Main.java:43)
跟踪实现有效。我们甚至可以看到类加载尝试。但是,javac失败,因为缺少权限。原因是,通过system属性安装安全管理器后,默认的Java安全策略处于活动状态,并且未授予所需的权限。要解决此问题,您可以提供最少的自定义策略,也可以checkPermission使用空的实现覆盖该方法。在这种情况下,我选择了最小策略:
grant {
permission java.security.AllPermission "", "";
};
有了适当的政策,我们可以重新测试:
$ java -Djava.security.policy=test.policy -Djava.security.manager=TraceSecurityManager com.sun.tools.javac.Main Test.java
Read: /home/user/com/sun/tools/javac/resources/spi/compilerProvider.class
Read: /home/user/com/sun/tools/javac/resources/compiler_en.properties
Read: /home/user/com/sun/tools/javac/resources/compiler_en_US.properties
Read: Test.java
Read: Test.java
Read: /usr/lib/jvm/java-11-openjdk-11.0.10.0.9-1.el7_9.x86_64/lib/modules
Read: /usr/lib/jvm/java-11-openjdk-11.0.10.0.9-1.el7_9.x86_64/lib/modules
Read: /usr/lib/jvm/java-11-openjdk-11.0.10.0.9-1.el7_9.x86_64/lib/jfxrt.jar
Read: /home/user/META-INF/services/java.nio.file.spi.FileSystemProvider
Read: /usr/lib/jvm/java-11-openjdk-11.0.10.0.9-1.el7_9.x86_64/lib/modules
Read: /usr/lib/jvm/java-11-openjdk-11.0.10.0.9-1.el7_9.x86_64/lib/modules
Read: Test.java
Read: /home/user/Test.java
Read: ./.bash_logout
Read: /home/user/.bash_logout
Read: ./.bash_profile
Read: /home/user/.bash_profile
Read: ./.bashrc
Read: /home/user/.bashrc
[...]
Read: /home/user/com/sun/tools/javac/resources/spi/ctProvider.class
Read: /home/user/com/sun/tools/javac/resources/ct_en.properties
Read: /home/user/com/sun/tools/javac/resources/ct_en_US.properties
Read: /home/user/TraceSecurityManager.class
Read: /home/user/Test.class
Read: /home/user
Write: /home/user/Test.class
Read: Test.java
这次,我们获得了完整的javac文件系统访问跟踪。还可以在运行时启用安全性管理器,如果由于某种原因而无法控制Java命令行,这将非常有用:
System.setSecurityManager(new TraceSecurityManager());
在这种特定情况下,由于默认策略未处于活动状态,因此不需要自定义策略。
学习资料免费领取群:3907814
使用安全管理器来跟踪文件系统访问肯定不是最好的选择,因为可能缺少与调试方案相关的详细信息,但是如果您没有其他选择并且需要完成工作或开销很小,则这是一个很好的折衷方案。跟踪是必需的。
以上是关于如何使用Java跟踪JVM文件系统访问的主要内容,如果未能解决你的问题,请参考以下文章