1

I am new to Java programming and have a question that I have been curious about. Any help will be appreciated :)

How are private, package-private, protected, and public variables differentiated behind the scenes, so as to keep variables safe?

By safe I mean for example, how does it make sure that private variables are accessible only to methods inside the class?

I want to know what actually happens inside the computer/JVM. Does Java have a different memory space for each of these types? And if so what makes the different memory spaces inaccessible? After all it is still in the memory right?

Thank you in advance :-)

Boann
  • 48,794
  • 16
  • 117
  • 146
Sirius
  • 61
  • 6
  • I don't think so, the other question asks the difference, this one asks what is happening. – CaffeineToCode May 28 '15 at 18:05
  • 2
    A Security Manager can be used to prevent access to private properties. Other than that, AFAIK, there isn't a special space for those. It is just a semantic error to access a field that is out of scope. That's why reflection can bypass it - given the Security Manager ain't in the way. – acdcjunior May 28 '15 at 18:05
  • @necreaux not a duplicate – Brandon Ling May 28 '15 at 18:06
  • Actually, I do believe final local variables are stored seperatly. – CaffeineToCode May 28 '15 at 18:07
  • I'm pretty sure the the access restrictions that java applies are purely at compile time. Java looks at your code, and and doesn't compile if it sees you breaking a rule (like trying to access a private variable outside of a class). – jmrah May 28 '15 at 18:09
  • 1
    @jrahhali Java also restricts access at runtime in the JVM (this is to help prevent issues when using the reflection API). – neuronaut May 28 '15 at 18:25
  • Thank you all for your time :-) Please do check my comments on the answers below for greater clarity on my question. BTW why was the question down voted...Did I do anything wrong ? :-o – Sirius May 28 '15 at 19:07

3 Answers3

3

Visibility scoping is implemented in two places in Java: in the compiler and in the JVM that executes the bytecode.

First, the compiler limits visibility of variables flagged with public, protected and private keywords (also note that Java has a fourth scope, called the default scope, that was what you get when you declare a variable without one of the three keywords). The differences are documented elsewhere (see In Java, difference between default, public, protected, and private or any good books on Java programming).

Second, and I think this is more what you are asking about, is that Java protects access to variables with private, protected and the default scope within the JVM at runtime. This primarily applies to Java's reflection API (if your non-reflection code compiles you know it isn't accessing anything it isn't allowed to access and thus can't run into runtime visibility problems). For example, say you've got this in Foo.java:

// class with a private member variable
public class Foo {
    private int bar = 0;
}

And then you try to access bar from another class using reflection in Test.java:

import java.lang.reflect.*;

// This class won't have access to Foo's member 'bar'
public class Test {

    void doStuff() {
        // create a new instance of Foo
        Foo foo = new Foo();
        try {
            // use reflection to get the variable named 'bar'
            Field barField = foo.getClass().getDeclaredField("bar");

            // attempt to access the value of 'bar' which will throw an exception
            System.out.println(barField.get(foo));

       } catch (NoSuchFieldException e) {
           throw new RuntimeException(e);
       } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
       }
    }

    public static void main(String[] args) {
        new Test().doStuff();
    }

}

You would get an exception indicating you have no access to that variable. There are ways to circumvent this, but the point here is that by default the JVM protects access to variables (and methods and classes) outside the scope you'd normally be able to see.

Addendum

Java doesn't typically "hide" anything since it doesn't need to. Neither the Java language nor the JVM bytecode have access to the pointers used behind the scenes and there's also no other way through the language or the reflection API to access arbitrary locations in memory and thus no way (with one exception -- see below) to read the value of a variable to which you don't have access. When using reflection the JVM simply checks a flag (initially set by the compiler) to see if the current code has access to the variable or method being accessed and then either allows the access or throws an exception.

The exception I mentioned is a reflection API call that can turn off the access checking for a given variable or method. For example, to avoid the exception from my previous example you could do this:

...
Field barField = foo.getClass().getDeclaredField("bar");
// mark the variable 'bar' as accessible
barField.setAccessible(true);
// attempt to access the value of 'bar' which will throw an exception
System.out.println(barField.get(foo));
...
Community
  • 1
  • 1
neuronaut
  • 2,689
  • 18
  • 24
  • Thank you for the help. The 'Compiler Check' part makes sense..Could you please elaborate on the second part of your answer..I didn't exactly get you. What is it that JAVA 'hides' to protect a variable...The address to the data? If so what keeps the address safe, too? :-P XD – Sirius May 28 '15 at 19:01
  • @Sirius I've updated my answer with some hopefully helpful clarifications. – neuronaut May 28 '15 at 21:13
1

You should spend a little time browsing the Java Virtual Machine Spec if you're interested. In particular, section 4.5 defines how the attributes for a field are stored and referred to, while section 5.4.3.2 discusses how fields are actually retrieved.

It boils down to resolving the field (first resolving the class if need be) and then checking whether the field is accessible to the calling code. AFAICT there is no special space for private fields.

dcsohl
  • 7,186
  • 1
  • 26
  • 44
  • Thank you for the help...Interesting stuff, but still it doesn't answer what I want to know. How JAVA restricts access upon learning that the field attribute is private? Like does it hide the address to data? – Sirius May 28 '15 at 19:03
1

Java uses code verification to enforce it’s rules. In the Java bytecode, there are no memory adresses but still distinct dedicated instructions for accessing fields of an instance, static fields, local variables or the operand stack. Since the instructions explicitly access fields, the Verifier can check whether the class containing the instruction has the right to access that field.

It’s important to understand that this happens only once for a particular piece of code, as the validity doesn’t change, thus verified code won’t be verified again on subsequent executions, so the verification imposes only a one-time overhead.

There are different strategies allowed, regarding when to verify a method’s code, but of course, the verification must happen before the first execution of a piece of code, which is before a JIT may compile the byte code to machine code which really uses memory addresses for accessing fields.

See also “The Java® Virtual Machine Specification, §4.10. Verification of class Files”

Holger
  • 285,553
  • 42
  • 434
  • 765