Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: accessing protected fields from inner class

Recently I've faced a problem getting a runtime error java.lang.IllegalAccessError when trying to access from inner class a protected field declared in outer's parent class that was loaded by a different class loader. Briefly:

  1. Class Parent has protected field p.
  2. Class Outer extends Parent.
  3. Class Inner is an inner class defined in class Outer.
  4. Inside Inner class there's a code: Outer.this.p.
  5. All classes are declared in the same package.

Normally it's compiled and runs fine until Parent and Outer class are loaded by different class loaders. In this case we get java.lang.IllegalAccessError when trying to access Outer.this.p from Inner. I found an old bug report (which appeared to be a feature) describing this behavior:

https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6258289

But resolution sounds contradictive to me:

The key is that in the failing case the inner class isn't in the same package (and isn't a subclass of) ConcreteCommand/AbstractCommand. This is simply a violation of the Java specification for protected classes.

It sounds correct. But if we declare Parent and Outer classes in different packages but load with the single class loader (simply create sample console app without any jar loadings) we don't get any errors. So technically it's a violation of Java spec for protected classes but since we use an inner class it works.

So we have different behavior for two cases of "different packages".

  1. Declared in different packages, loaded by single class loader - OK.
  2. Declared in single package, loaded by different class loaders - NOT OK.

Could someone give a clear explanation of how inner class gets access to parent's fields and why it works differently for two cases?

like image 735
Timofei Davydik Avatar asked Jul 13 '20 11:07

Timofei Davydik


People also ask

How do I access protected inner classes?

In order to access your demo12 inner class from demo2 class, demo2 class has to extend demo1 . More over, inner classes are connected with instances of the class, so you can not call it directly from the static method. Check the difference between inner and nested classes. Show activity on this post.

Can protected variables be accessible from class to class?

Protected Access Modifier - Protected Variables, methods, and constructors, which are declared protected in a superclass can be accessed only by the subclasses in other package or any class within the package of the protected members' class. The protected access modifier cannot be applied to class and interfaces.

Can we access protected member outside the class in Java?

A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.

Can inner class access private variables Java?

It can access any private instance variable of the outer class. Like any other instance variable, we can have access modifier private, protected, public, and default modifier. Like class, an interface can also be nested and can have access specifiers.


1 Answers

  • Same class loader it seems to be working
  • Did I get the question right?
  • Do you have any unit test case to reproduce your issue?

Parent Class

package p1;

public class Parent {
    
    protected String p = "Value from Parent";
    
    public void test() {
        System.out.println(p);
    }

}

Outer Class

package p1;

public class Outer extends Parent {

    class Inner {
        public void test() {
            Outer.this.p = "Value set from Inner";
            System.out.println(Outer.this.p);
        }
    }

    public void test() {
        new Inner().test();
    }
}

Main Class

package p1;

public class Main {

    public static void main(String[] args) {
        Parent p = new Parent();
        p.test();
        p = new Outer();
        p.test();
    }
}

Output

Value from Parent
Value set from Inner
like image 156
vijayan007 Avatar answered Oct 09 '22 03:10

vijayan007