X

IllegalAccessException is not a SecurityException

Guest Author


http-equiv="content-type">
IllegalAccessException is not a SecurityException




What is your first response when you see an application failed with href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/IllegalAccessException.html">java.lang.IllegalAccessException
Is it caused by insufficient security permissions?  Not
really.  IllegalAccessException is not a subtype of href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/SecurityException.html">java.lang.SecurityException. 
Let's say you want to call a private method in anotehr class, which is
normally
not allowed by javac.  But you know you can bypass javac with
reflection like this:

 1 import java.lang.reflect.Method;
class="line-number"> 2 public class="java-keywords">class CallFoo {
class="line-number"> 3     public class="java-keywords">static void class="java-layer-method">main(String args[]) class="java-keywords">throws Exception {
class="line-number"> 4         Class fooClass = Class.class="java-layer-method">forName(class="java-string-literal">"Foo");
5         Foo foo = (Foo) fooClass.class="java-layer-method">newInstance();
class="line-number"> 6         Method helloMethod = fooClass.class="java-layer-method">getDeclaredMethod(class="java-string-literal">"hello");
class="line-number"> 7         helloMethod.class="java-layer-method">invoke(foo);
class="line-number"> 8     }
9 }
class="line-number"> 1 public class="java-keywords">class Foo {
2 class="java-keywords">    private void class="java-layer-method">hello() {
3         System.out.class="java-layer-method">println(class="java-string-literal">"This is Foo.hello");
class="line-number"> 4     }
5 }



C:\\ws\\nb\\Simple>java CallFoo


Exception in thread "main" java.lang.IllegalAccessException: Class
CallFoo can not access a member of class Foo with modifiers "private"

        at
sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)

        at
java.lang.reflect.Method.invoke(Method.java:578)

        at
CallFoo.main(CallFoo.java:7)




My first response was that I don't have sufficient security
permission.  But there is no SecurityManager installed in the
above test run, and so both Foo and CallFoo classes should have href="http://java.sun.com/j2se/1.5.0/docs/api/java/security/AllPermission.html">AllPermissions.



Well, the real cause is that we need to suppress Java language access
checking, in order to reflectively invoke a private method in another
class, with href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/AccessibleObject.html">setAccessible(true):


 6 Method helloMethod = fooClass.class="java-layer-method">getDeclaredMethod(class="java-string-literal">"hello");
style="color: rgb(0, 153, 0);" class="line-number"> 7style="color: rgb(0, 153, 0);"> style="color: rgb(0, 153, 0);" class="java-keywords">    ifstyle="color: rgb(0, 153, 0);">(!helloMethod.style="color: rgb(0, 153, 0);" class="java-layer-method">isAccessiblestyle="color: rgb(0, 153, 0);">()) {style="color: rgb(0, 153, 0);">class="line-number"> 8         helloMethod.style="color: rgb(0, 153, 0);" class="java-layer-method">setAccessiblestyle="color: rgb(0, 153, 0);">(style="color: rgb(0, 153, 0);" class="java-keywords">truestyle="color: rgb(0, 153, 0);">);style="color: rgb(0, 153, 0);">class="line-number"> 9     }
class="line-number">10 helloMethod.class="java-layer-method">invoke(foo);


Furthermore, when a SecurityManager is enable, we need extra
permissions to call setAccessible(true)
Otherwise, we get:



C:\\ws\\nb\\Simple>java -Djava.security.manager CallFoo

Exception in thread "main" java.security.AccessControlException: access
denied (java.lang.reflect.ReflectPermission suppressAccessChecks)

        at
java.security.AccessControlContext.checkPermission(AccessControlContext.java:264)

        at
java.security.AccessController.checkPermission(AccessController.java:427)

        at
java.lang.SecurityManager.checkPermission(SecurityManager.java:532)

        at
java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:107)

        at
CallFoo.main(CallFoo.java:8)




We only want to grant this suppressAccessChecks permission
to trusted code source, definitely not to all classes in the call
stack.  So we would modify CallFoo.java:

 1 import java.lang.reflect.InvocationTargetException;
class="line-number"> 2 import java.lang.reflect.Method;
class="line-number"> 3 import java.security.AccessController;
class="line-number"> 4 import java.security.PrivilegedActionException;
class="line-number"> 5 import java.security.PrivilegedExceptionAction;

class="line-number"> 6 public class="java-keywords">class CallFoo {
class="line-number"> 7     public class="java-keywords">static void class="java-layer-method">main(String args[]) class="java-keywords">throws Exception {
class="line-number"> 8         doCallFoo();
class="line-number"> 9     }
10
class="line-number">11     public class="java-keywords">static void class="java-layer-method">doCallFoo() class="java-keywords">throws IllegalAccessException, ClassNotFoundException, NoSuchMethodException,
class="line-number">12             InvocationTargetException, InstantiationException, PrivilegedActionException {
class="line-number">13           Class fooClass = Class.class="java-layer-method">forName(class="java-string-literal">"Foo");
14 class="java-keywords">        final Foo foo = (Foo) fooClass.class="java-layer-method">newInstance();
class="line-number">15         final Method helloMethod = fooClass.class="java-layer-method">getDeclaredMethod(class="java-string-literal">"hello");
class="line-number">16
17         AccessController.class="java-layer-method">doPrivileged(class="java-keywords">new PrivilegedExceptionAction() {
class="line-number">18             public Object class="java-layer-method">run() throws Exception {
class="line-number">19 class="java-keywords">                if(!helloMethod.class="java-layer-method">isAccessible()) {
class="line-number">20                     helloMethod.class="java-layer-method">setAccessible(class="java-keywords">true);
21                 }
class="line-number">22                 helloMethod.class="java-layer-method">invoke(foo);
class="line-number">23 class="java-keywords">              return null;
class="line-number">24             }
class="line-number">25         });
26     }
class="line-number">27 }


In addition, we specify our security requirement in foo.policy:



// Core classes get all permissions

grant codeBase "file:./-" {

    permission java.lang.reflect.ReflectPermission
"suppressAccessChecks";

};




Finally, this test can pass with or without SecurityManager:



C:\\ws\\nb\\Simple>java -Djava.security.manager
-Djava.security.policy=foo.policy CallFoo

This is Foo.hello



C:\\ws\\nb\\Simple>java CallFoo

This is Foo.hello

technorati tags: , ,



Join the discussion

Comments ( 3 )
  • craig e. Wednesday, November 7, 2007

    thanks alot this helped me out


  • guest Wednesday, November 18, 2009

    hi


  • guest Friday, June 17, 2011

    Hi craig,

    I did not understand below line.

    "In addition, we specify our security requirement in foo.policy:"

    Can you guide me where this application specific foo.policy file exists ? or where we need to put this policy file ?

    Thanks in advnace,

    Pratik


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.