14

I have two classes.

Class A has protected method m(), a is an instance of A.

Class B is in the same package as class A.

I am trying to access a.m() but I am getting IllegalAccessError...

What's wrong?

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • 4
    Please produce a short but complete program which demonstrates the problem. This sounds very odd. Do you have any obfuscation etc involved? – Jon Skeet Aug 02 '10 at 10:02

4 Answers4

23

The compiler should catch errors like this. As you are apparently getting this at runtime, something odd has happened. Probably you have changed the source code but fully recompiled.

Another potential, but obscure, problem is loading the classes through different class loaders. Classes loaded from different class loaders will be in different packages even if the package name is the same (in the same way as classes with the same name loaded by different class loaders will be different classes).

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • You might have to restart your application. I just had the same experience while changing a running application (i.e. could be a bug in the hot code replacement) – Maximilian Böhm Jun 28 '22 at 13:20
19

This can happen if classes A and B are loaded by different classloader. The jvm then considers these classes to be in different "runtime packages". Quoting from the jvm specification, section 5.3:

At run time, a class or interface is determined not by its name alone, but by a pair: its fully qualified name and its defining class loader. Each such class or interface belongs to a single runtime package. The runtime package of a class or interface is determined by the package name and defining class loader of the class or interface.

And in section 5.4.4:

A field or method R is accessible to a class or interface D if and only if any of the following conditions is true:

...

R is either protected or package private (that is, neither public nor protected nor private), and is declared by a class in the same runtime package as D.

Jörn Horstmann
  • 33,639
  • 11
  • 75
  • 118
  • I suspect this might be causing my issue, but not sure where in the stack a second class loader would be pulled in or how to debug. But will look around.... – Mark Bennett Oct 14 '11 at 20:38
  • I found this answer after some googling about another problem in which my class was in the same named package, but a different runtime package. This makes things make so much more sense! +1 – vergenzt Mar 26 '13 at 00:53
-1

It has to work, see the following example that works just fine:

package com.stackoverflow;

public class TEST
{
  static class A {
    protected void m()
    {
      System.out.println("hello from A.m()");
    }
  }

  static class B {

    public B()
    {
      a.m();
    }

    private A a = new A();
  }

  /**
   * @param args
   */
  public static void main(String[] args)
  {
    B b = new B();
  }
}

which prints out the intended message: "hello from A.m()"

"The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package."

See Controlling Access to Members of a Class.

Gregory Pakosz
  • 69,011
  • 20
  • 139
  • 164
  • 2
    "The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package." http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html – Mike Tunnicliffe Aug 02 '10 at 10:04
  • Or leave it with default access (i.e. no access specifier) to allow package access. – Scott Aug 02 '10 at 10:04
  • i changed the content of the answer, previous content was buggy, sorry for that and thx @fd; are you sure your class B is really in the same package as class A? – Gregory Pakosz Aug 02 '10 at 10:06
  • 1
    Content is now correct, helpful, but doesn't directly answer the question (probably need more info from the question) – Mike Tunnicliffe Aug 02 '10 at 10:07
  • it should work; if it doesn't it's because of other causes like class loader issues or else – Gregory Pakosz Aug 02 '10 at 13:10
-2

compiler should catch errors like this. As you are getting this at runtime, something wrong has been happened. Most probably you have changed the source code which is fully recompiled.

It must work. Here is a running example -

**

  • CLASS A

**

package com.test;

public class A {

  protected void m(){
  System.out.println("Hi Stackoverflow");
 }

}

**

  • CLASS B

**

package com.test;

public class B{

public static void main(String[] args) {
  A a = new A();
  a.m();
 }

}

which prints the expected string

Hi Stackoverflow

Neel
  • 429
  • 7
  • 17