Bug 126712 - [compiler] IllegalAccessException on attempt to access an accessible member via reflection
Summary: [compiler] IllegalAccessException on attempt to access an accessible member v...
Status: VERIFIED INVALID
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 3.3 M7   Edit
Assignee: Maxime Daniel CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-02-07 07:06 EST by Maxime Daniel CLA
Modified: 2007-05-03 20:55 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Maxime Daniel CLA 2006-02-07 07:06:44 EST
Build id: I20060131-1200

The setup is as follows:
- a package visible class defines a public method;
- in the same package, a public class extends the first one;
- from another package, a class uses the said method.
When the method is called directly, the code compiles and produces the expected result. When the method is called through the reflection API, the code compiles OK, but we get an exception at runtime. This shows that the behavior is different  depending on the access method, which should not be according to the documentation for IllegalAccessException.

The same holds true for a field.

I put in place RuntimeTests number 600 and 601 to show the problem.
Comment 1 Olivier Thomann CLA 2007-02-08 21:50:00 EST
It fails as well with javac 1.3, 1.4 and 1.5.
Only in 1.6 a bridge method is added in Y for accessing the method foo in Z and it runs fine.
So I would modify the test case for 1.3, 1.4 and 1.5.
Comment 2 Olivier Thomann CLA 2007-02-08 21:57:34 EST
In 1.6 mode, a bridge method is added in Y.

// Compiled from Y.java (version 1.6 : 50.0, super bit)
public class p.Y extends p.Z {
  
  // Method descriptor #6 ()V
  // Stack: 1, Locals: 1
  public Y();
    0  aload_0
    1  invokespecial p.Z() [1]
    4  return
      Line numbers:
        [pc: 0, line: 3]
  
  // Method descriptor #6 ()V
  // Stack: 1, Locals: 1
  public bridge synthetic void foo();
    0  aload_0
    1  invokespecial p.Z.foo() : void [2]
    4  return
      Line numbers:
        [pc: 0, line: 3]
}

So it seems that we have a missing bridge method.
Comment 3 Maxime Daniel CLA 2007-04-02 08:36:31 EDT
(In reply to comment #1)
> It fails as well with javac 1.3, 1.4 and 1.5.
> Only in 1.6 a bridge method is added in Y for accessing the method foo in Z and
> it runs fine.
> So I would modify the test case for 1.3, 1.4 and 1.5.
> 
If you look at the test cases, I have set on one line a direct method call (resp. field access) and on the following line a method call (resp. field access) that uses the reflection API. I cannot see how a call that is legit with respect to visibility rules when compiled directly could raise an IllegalAccessException when mimicked using the reflection API. I would hence contend that javac 1.3, 1.4 and 1.5 have a bug here, and maintain my test cases unchanged.
Philippe, what do you think?

Comment 4 Maxime Daniel CLA 2007-04-02 09:10:21 EDT
javac/java 6 does not do better than us on the second test case (fields). And in the case of fields, I am not sure bridge methods would help in any way.
I wonder if we should not consider this problem as a bug on the Java reflection API, since it seem unable to apply the same visibility rules as the compiler does, despite the documentation of Field#get and Method#invoke of java.lang.reflect.

Searching for java bugs in that area, I found 
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6342411
that explains why javac 6 adds the bridge method: this is a mitigation of the fact that the reflection API misbehaves. Their analysis converges with mine on one point: there is nothing the compiler can do for fields.

I suspect that debuggers use an implementation of the reflection APIs that do not check accessibility at all, since they can access private members (or else they use a radically different technique?), and that only user code that uses reflection for other uses get affected.

Philippe, could you please comment on what you think we should do here, amongst:
a - do nothing; this is a reflection implementation bug;
b - mitigate the impact of the reflection implementation bug for method as javac does by adding bridge methods;
c - b, but in 1.6+ compatibility modes only (because javac 1.3, 1.4, 1.5 do not generate the bridge methods).
Comment 5 Philipe Mulet CLA 2007-04-02 11:45:10 EDT
Looks like the compiler hacking to workaround a library bug (reflect).
If we do something, it would be to mimick ref compiler here (with a TODO to remove the hack at some later point, if the libs are fixed), so option (c).
Comment 6 Maxime Daniel CLA 2007-04-03 03:49:15 EDT
My personal preference would go to INVALID, and only consider hacking if someone else than myself complains. Would that sound reasonable?
Comment 7 Maxime Daniel CLA 2007-05-02 03:58:02 EDT
Since none protests, going to INVALID.
Activated the tests (as expecting a runtime failure).
Comment 8 Olivier Thomann CLA 2007-05-02 13:23:48 EDT
Disactivated the tests as they are VM dependent.
Adding bug 185182 to track the issue with the tests.
Comment 9 Olivier Thomann CLA 2007-05-03 20:55:14 EDT
Verify for 3.3M7 with I20070503-1400.