<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Neuroning: Violating Java's privacy</title>
    <link>http://neuroning.com/articles/2007/02/19/violating-javas-privacy</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>My mind workout on Software Development</description>
    <item>
      <title>Violating Java's privacy</title>
      <description>&lt;p&gt;I  found myself in the need to invoke a private method of a Java
class that was out of my control. I really needed it.&lt;/p&gt;

&lt;p&gt;So, I went ahead and &lt;em&gt;violated&lt;/em&gt; the method&amp;#8217;s privacy declaration via
reflection. You can (under certain circumstances) invoke methods which
are declared as private using the Reflection APIs (&lt;code&gt;java.lang.reflect&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;But before using reflection, I created two classes:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class A {
  public String method1() {
    return "Hello World!";
  }
}

class B {
  public static void main(String[] args) {
    A a = new A();
    System.out.println(a.method1());
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;They compiled, and &lt;code&gt;java B&lt;/code&gt; said &amp;#8220;Hello World!&amp;#8221; as expected.&lt;/p&gt;

&lt;p&gt;Then, I made A&amp;#8217;s method &lt;code&gt;private&lt;/code&gt; and recompiled A. And I run &lt;code&gt;java B&lt;/code&gt; again. Nothing changed. It just worked again.&lt;/p&gt;

&lt;p&gt;That cannot be right. This would mean you can handcraft a class with the
same name and methods as the original one but making everything
&lt;code&gt;public&lt;/code&gt;.  Then you could use this class only at compilation time,
allowing your code to call any method. (Or, one could modify
the Java compiler to ignore access declarations altogether).&lt;/p&gt;&lt;p&gt;Returning to the reflection APIs for a sec., here&amp;#8217;s how I called private method
&lt;code&gt;ProcessService.getSession(String)&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Class clazz = ProcessService.class;
Class[] params = new Class[] { String.class };
Method m = clazz.getDeclaredMethod("getSession", params);

m.setAccessible(true); // allow access, as if it were public

Object session = m.invoke(this, new Object[] {sessionId});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Java compiler enforces access restrictions at compilation
time. But it&amp;#8217;s the Security Manager (an object of type
java.lang.SecurityManager) the man on duty at runtime. The above code
works because, by default, the JVM does not use a SecurityManager.&lt;/p&gt;

&lt;p&gt;For the curious, the implementation for method
&amp;#8220;setAccessible(boolean)&amp;#8221; (part of the JDK) looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public void setAccessible(boolean flag) throws SecurityException {
  SecurityManager sm = System.getSecurityManager();
  if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
  setAccessible0(this, flag);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It simply asks the current SecurityManager for permission before
actually changing the &amp;#8220;accessible&amp;#8221; property. In general, before any
&amp;#8220;sensitive&amp;#8221; operation, the code in the JDK asks the SecurityManager
for permission.&lt;/p&gt;

&lt;p&gt;You enable the default SecurityManager passing
&lt;code&gt;-Djava.security.manager&lt;/code&gt; to the java command. This would make the
first code snipet above to throw an AccessControlException. Both
methods &lt;code&gt;Class.getDeclaredMethod()&lt;/code&gt; and &lt;code&gt;Method.setAccessible()&lt;/code&gt;
are guarded by the SecurityManager.&lt;/p&gt;

&lt;p&gt;To allow the above use of reflection with the SecurityManager enabled,
one must define a security
&lt;a href="http://java.sun.com/j2se/1.5.0/docs/guide/security/PolicyFiles.html"&gt;policy&lt;/a&gt;
for explicitly permitting those operations.&lt;/p&gt;

&lt;p&gt;Anyway, back to my original concern of class B being able to invoke class A&amp;#8217;s
private method directly. I could try to run it with the
SecurityManager enabled:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ java -Djava.security.manager B
Hello World!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It still works. So, I run the same test but from an applet (a more
restricted container):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import java.awt.Label;
import java.applet.Applet;
public class BApplet extends Applet
{
  public void start() {
    A a = new A();
    add(new Label(a.method1()));
  }
}

&amp;lt;html&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;applet width="300" height="300" code="BApplet.class"&amp;gt;
    &amp;lt;/applet&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now it &lt;em&gt;did&lt;/em&gt; fail, finally:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ appletviewer BApplet.html
java.lang.IllegalAccessError: tried to access method
                  A.method1()Ljava/lang/String; from class BApplet
  at BApplet.start(BApplet.java:7)
  at sun.applet.AppletPanel.run(AppletPanel.java:414)
  at java.lang.Thread.run(Thread.java:595)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For this particular type of runtime checks, the Security Manager is
clearly not involved. Nothing shows up in the StackTrace. It happens
at a lower level, in the JVM itself. Makes sense now: it would be
really inefficient to invoke the SecurityManager for every non-public
method call&amp;#8230; (and who&amp;#8217;d check the calls to the SecurityManager
itself!?).&lt;/p&gt;

&lt;p&gt;But still, Why does it work with the java command, but fails within an
applet?&lt;/p&gt;

&lt;p&gt;To help with performace, the JVM only enforces these checks on classes
loaded by custom classloaders. Classes loaded by the standard class
loaders (bootstrap, extensions and System) are considered
&lt;em&gt;trusted&lt;/em&gt;. There are &amp;#8220;levels&amp;#8221; of trust actually, (bootstrap being the
most trusted), but for this particular case, even the System
(classpath) class loader trusted my class.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.artima.com/insidejvm/ed2/"&gt;Inside the JVM&lt;/a&gt; covers the JVM
internals extensively, including &lt;a href="http://www.artima.com/insidejvm/ed2/security.html"&gt;security and class
loaders&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Mon, 19 Feb 2007 22:49:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:7be96d73-24b4-4f34-9d31-1ea2f89ce1a9</guid>
      <author>F</author>
      <link>http://neuroning.com/articles/2007/02/19/violating-javas-privacy</link>
      <category>Java</category>
      <category>Security</category>
      <trackback:ping>http://neuroning.com/articles/trackback/164</trackback:ping>
    </item>
  </channel>
</rss>
