Use a custom security manager as a low overhead alternative to native tracers.
Native tracing tools are always the first choice for tracking file system access to Java applications. On Windows, use Process Monitor to track I / O. On Linux, use strace. Other platforms also provide similar functions.
By tracing directly in Java, you can address environmental constraints. For example, when the cap is missing_ SYS_ strace is not available in the container of ptrace function, and the container host is not always accessible. In addition, the potential lighter weight tracking mechanism can be easily tracked in the production environment.
To follow the Java route, you can extend to implement your own security manager Java lang.SecurityManager. This class provides checkRead, checkWrite and checkDelete methods. Once the code attempts to access them, they will be called.
An example implementation:
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); } }
To test the sample, we use the Java compiler as the test object. To enable the trace security manager, we set the appropriate system properties and execute the command test. Using a valid Java source file 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)
Tracking is effective. We can even see class loading attempts. However, javac failed because of a lack of permissions. The reason is that after installing the security manager through the system attribute, the default Java security policy is active and the required permissions are not granted. To solve this problem, you can provide a minimum of custom policies, or you can override this method with an empty implementation of checkPermission. In this case, I chose the minimum strategy:
grant { permission java.security.AllPermission "", ""; };
With appropriate policies, we can retest:
$ 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
This time, we have obtained the complete javac file system access trace. You can also enable the security manager at run time, which is useful if you cannot control the Java command line for some reason:
System.setSecurityManager(new TraceSecurityManager());
In this particular case, there is no need to customize the policy because the default policy is not active.
Free collection group of learning materials: 3907814
Using security manager to track file system access is certainly not the best choice, because there may be a lack of details related to the debugging scheme, but this is a good compromise if you have no other choice and need to complete the work or the cost is small. Tracking is required.
Original link: https://segmentfault.com/a/1190000039858551