You're supposed to familiar with the java.security.debug property, otherwise please refer to the sample chapter of "Java Security".
Before Java 6, if the security debug property, java.security.debug, is enabled, a large volume of debug output will be dumped. For example, if java.security.debug deinfed as access:stack, every stack will be dumped if a permission is checked on. Even for a simple application, the output normally runs over several pages. In server products, such as Sun Web Server and App Server, the amount of output is overwhelming, analysis them manually is a nightmare. So customers often give up in frustration while trying to follow it to diagnose problems.
Things get changed at Java 6, the java security packages introduced two new java.security.debug options, permission and codebase. Let's have a look at the help message of security debugger.
$ java -Djava.security.debug=help Foo
all turn on all debugging
access print all checkPermission results
combiner SubjectDomainCombiner debugging
gssloginconfig
GSS LoginConfigImpl debugging
jar jar verification
logincontext login context results
policy loading and granting
provider security provider debugging
scl permissions SecureClassLoader assigns
The following can be used with access:
stack include stack trace
domain dump all domains in context
failure before throwing exception, dump stack
and domain that didn't have permission
The following can be used with stack and domain:
permission.<classname>
only dump output if specified permission
is being checked
codebase.<URL>
only dump output if specified codebase
is being checked
Note: Separate multiple options with a comma
Note that there's a bug on the help message that "permission.<classname>" should be "permission=<classname>", and "codebase.<URL>" should be "codebase=<URL>". And in the two options, spaces are not allowed before and after the sign "=".
Let's show the two options with a sample class, Foo.
// Sample class to illustrate debug options
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class Foo {
public static void main(String[] args) throws Exception {
ObjectInputStream ois = null;
try {
FileInputStream fis = new FileInputStream("./foo.obj");
ois = new ObjectInputStream(fis);
Object dummy = ois.readObject();
} finally {
if (ois != null) {
ois.close();
}
}
}
}
permission=<classname>:
permission=<classname> option is used with stack trace or domain option, when a certain classname is specified, the security debugger will only dump the stacks or the domain that checking the specified permission. Here, classname is the canonical class name of the specified permission, and the classname is case sensitive.
The option is particularly useful for customers who have their own permissions to take care of, or only care to follow the evaluation details of some certain permissions.
For the above sample class, the Java security will check the following permissions on Foo.main():
- java.io.FilePermission (1 time)
- java.lang.RuntimePermission (1 time)
- java.lang.reflect.ReflectPermission (5 times)
Sometimes, users maybe only want to trace the stacks that checking java.io.FilePermission, or really do not want to care java.lang.reflect.ReflectPermission. Try to run the example and see what happened.
$ java -Djava.security.manager \
-Djava.security.debug=access,stack Foo
(The output omitted)
$ java -Djava.security.manager \
-Djava.security.debug=access,stack,permission=java.io.FilePermission Foo
java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Thread.java:1206)
at java.security.AccessController.checkPermission(AccessController.java:532)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.checkRead(SecurityManager.java:871)
at java.io.File.isDirectory(File.java:752)
at sun.net.www.ParseUtil.fileToEncodedURL(ParseUtil.java:242)
at sun.security.provider.PolicyFile.canonicalizeCodebase(PolicyFile.java:1806)
at sun.security.provider.PolicyFile.access$700(PolicyFile.java:263)
at sun.security.provider.PolicyFile$5.run(PolicyFile.java:1220)
at sun.security.provider.PolicyFile$5.run(PolicyFile.java:1218)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.provider.PolicyFile.getPermissions(PolicyFile.java:1217)
at sun.security.provider.PolicyFile.getPermissions(PolicyFile.java:1165)
at sun.security.provider.PolicyFile.implies(PolicyFile.java:1120)
at java.security.ProtectionDomain.implies(ProtectionDomain.java:213)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:301)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.checkRead(SecurityManager.java:871)
at java.io.FileInputStream.<init>(FileInputStream.java:100)
at java.io.FileInputStream.<init>(FileInputStream.java:66)
at Foo.main(Foo.java:11)
access: access allowed (java.io.FilePermission /some/somedir read)
$ java -Djava.security.manager \
-Djava.security.debug="access,stack,permission=java.io.FilePermission \
permission=java.lang.RuntimePermission" Foo
(The output omitted)
codebase=<URL>:
codebase=<URL> option is used with stack trace or domain option, when a certain codebase is specified, the security debugger will only dump the stacks or the protection domain that from the specified code source defined by the codebase. Here, URL is the location of the specified code base. Note that because the comma (',") is used as multi options separator, if the URL contains comma, the security debugger would not work properly as expected, it is recommended that the URL should not include character comma (','), semicolon (';'), and space.
This option would be useful when customer desires to trace the permissions impact of only the code in a given code souce, such as jar file.