JVM下是否有办法(暂时)阻止对System.out,System.in和System.err的完全访问?
创建一个根本不授予权限的空白策略后,我想在下面的函数中执行一些工作。 我希望调用System.out.println之类的功能失败,但他们不会。我有什么可以做的,或者我是一个太多的控制狂?
编辑#1:根据MrPixelDream建议使用System.setOut
,我将权限保持在最低限度,以确保run()
中的代码也无法调用System.setOut
或java.io.FileDescriptor.out
愚弄。
编辑#2 另外,由于流氓代码可能只是简单地执行了standardOutput.println
,因此我倾向于不保留对System.out
的引用,并将其设置为使用java.io.FileDescriptor.out
。
// Create blank permissions that barely allow executing code
java.security.Permissions perm = new java.security.Permissions();
// CodeSource domain for which these permissions apply (all files)
java.security.CodeSource code = new java.security.CodeSource(new java.net.URL("file:/*"),
null);
// ProtectionDomain
java.security.ProtectionDomain domain = new java.security.ProtectionDomain(code, perm);
// AccessControlContext
java.security.ProtectionDomain[] domains = new java.security.ProtectionDomain[1];
domains[0] = domain;
java.security.AccessControlContext context =
new java.security.AccessControlContext(domains);
// DON'T keep reference to standard output, it could be used directly
// PrintStream standardOut = System.out;
// Redirect output to dummy stream
System.setIn(new ByteArrayInputStream(new byte[0]));
System.setOut(new PrintStream(new ByteArrayOutputStream()));
System.setErr(new PrintStream(new ByteArrayOutputStream()));
// Do an action, subject to the given security context
java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<Void>() {
public Void run() {
// Do some work, side effects and all, but no I/O whatsoever
System.out.println("Will not print !");
// Try to fool around System.out with direct access from file descriptors (0, 1, 2)
java.io.PrintStream myOut =
new java.io.PrintStream(new java.io.FileOutputStream(java.io.FileDescriptor.out));
// Missing permission java.lang.RuntimePermission "setIO"
// Will throw java.security.AccessControlException
System.setOut(myOut);
// Missing permission java.lang.RuntimePermission "writeFileDescriptor"
myOut.println("Will throw java.security.AccessControlException !");
}
}, context);
// Now set back the old streams to have output again
System.setIn(new java.io.FileInputStream(java.io.FileDescriptor.in));
System.setOut(
new java.io.PrintStream(new java.io.FileOutputStream(java.io.FileDescriptor.out)));
System.setErr(
new java.io.PrintStream(new java.io.FileOutputStream(java.io.FileDescriptor.err)));
答案 0 :(得分:2)
Elliott Frisch的答案可以解决问题,但是你做完之后就无法获得输出。如果您打算暂时将输出静音,请使用以下代码:
public class RedirectedOutput {
public static void main(String[] args) {
// Save the old output stream to have the chance to set it back later
InputStream standardIn = System.in;
PrintStream standardOut = System.out;
PrintStream standardErr = System.err;
// Set useless streams
System.setIn(new ByteArrayInputStream(new byte[0]));
System.setOut(new PrintStream(new ByteArrayOutputStream()));
System.setErr(new PrintStream(new ByteArrayOutputStream()));
// Will not be shown
System.out.println("Hello World");
// Now set back the old streams to have output again
System.setIn(standardIn);
System.setOut(standardOut);
System.setErr(standardErr);
// Will be shown again
System.out.println("Finally we got the Hello");
}
}
您可以尝试这个应该完全可运行的示例。它应该是自我解释的。您正在使用setIn()
,setOut()
和setErr()
来更改流,然后将其保存,然后才能将其设置回来。
但如果您不需要任何输出,那么您最好使用Elliott的代码,因为我觉得它对资源更好。
答案 1 :(得分:1)
我不相信有一种方法可以暂时执行此操作,但您可以阻止它们写入或读取,直到JVM重新启动close()
它们之类的内容,
public static void main(String[] args) {
try {
System.in.close();
} catch (IOException e) {
e.printStackTrace();
}
System.err.close();
System.out.close();
System.out.println("Must not print !");
}
没有输出。