my dog learned polymorphism*
The moose likes Java in General and the fly likes Reflection access rules Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCA/OCP Java SE 7 Programmer I & II Study Guide this week in the OCPJP forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Reflection access rules" Watch "Reflection access rules" New topic
Author

Reflection access rules

Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

A very specific question:



But for the life of me, I can't figure out how to call foo() by reflection from inside pack1. Grabbing the Method object from Sub.class or from Sub.class.getSuperclass() doesn't work; both throw IllegalAccessException.

Now, of course, you can call setAccessible(true) on the method, but that can be rejected by a SecurityManager. Why should this be needed? If you can compile code that calls the method, why can't you call it reflectively without "cheating?"
[ September 10, 2004: Message edited by: Ernest Friedman-Hill ]

[Jess in Action][AskingGoodQuestions]
Dirk Schreckmann
Sheriff

Joined: Dec 10, 2001
Posts: 7023
Did you intend for Sub to extend Base?


[How To Ask Good Questions] [JavaRanch FAQ Wiki] [JavaRanch Radio]
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

Yes, thanks. I edited my post to reflect Dirk's comment.
[ September 10, 2004: Message edited by: Ernest Friedman-Hill ]
Maulin Vasavada
Ranch Hand

Joined: Nov 04, 2001
Posts: 1871
Hi Ernest,

How did you fixed it? Made the Base public?

Thanks
Maulin
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

Originally posted by Maulin Vasavada:

How did you fixed it? Made the Base public?


Aaak. I meant I edited my original post because Dirk pointed out that I left off "extends Base" when defining "Sub". I still don't know the answer to my question.
Lasse Koskela
author
Sheriff

Joined: Jan 23, 2002
Posts: 11962
    
    5
For me, the following works just fine:

Do you have some kind of a sadistic java.lang.SecurityManager implementation in use?


Author of Test Driven (2007) and Effective Unit Testing (2013) [Blog] [HowToAskQuestionsOnJavaRanch]
Maulin Vasavada
Ranch Hand

Joined: Nov 04, 2001
Posts: 1871
Hi Lasse,

I guess what Ernest is doing is something like,


This doesn't work for me as well.

It throws following exception,
java.lang.IllegalAccessException: Class pack2.Other can not access a member of class pack1.Base with modifiers "public"
at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at pack2.Other.main(Other.java:32)



Regards,
Maulin
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

Here's my Other class:



And I get (notice that "null" meaning "no security manager")




This is j2sdk1.4.2_05 on Linux. foo.isAccessible() returns "false".

What Java version are you using?
Maulin Vasavada
Ranch Hand

Joined: Nov 04, 2001
Posts: 1871
I guess its an incosistency between JVM Impl and Reflection Impl

Thinking if there is some way out...

Thanks
Maulin
Maulin Vasavada
Ranch Hand

Joined: Nov 04, 2001
Posts: 1871
I'm on Win XP,

java version "1.4.2_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_03-b02)
Java HotSpot(TM) Client VM (build 1.4.2_03-b02, mixed mode)

Thanks
Maulin
Maulin Vasavada
Ranch Hand

Joined: Nov 04, 2001
Posts: 1871
Hi all,

I pulled the API's source and in Method's invoke() I see,



That seems incorrect. The reason is, it checks if caller and callee (the DeclaringClass) match to have access which could be wrong as it is in the current case where we know Base and Other are in different package and Base is package protected. It should check for obj.getClass() and clazz compatibility. We know that we have Sub object which does have access to foo() so if we pass obj.getClass() instead of caller it should work..

But unfortunately I can't fix API nor I know consequences of doing what I have suggested

Regards,
Maulin
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[EFH]: But for the life of me, I can't figure out how to call foo() by reflection from inside pack1

Quite easily, actually. It's calling from inside pack2 that's hard.

I agree that there seems to be no good reason for this. I see the same behavior on Windows 2000 Pro using JDKs 1.3.1_11, 1.4.2_05, and 1.5.0.b2. Scrounging around at the Sun site I found it seems to be a known bug (for some time unfortuantely):

4071957
4283544

I don't see a good workaround unfortunately, other than setAccessible(). Or I suppose you might be able to do some sort of code generation or bytecode engineering to either modify the class to change the access, or create a new class and method in pack1 which can access the desired method for you. Which might be fun, actually, but is probably an inefficent use of your time. I assume we can't just tell the author of the Base class to make the darn thing public in the first place?


For what it's worth, I added my vote to both bug reports. (Had 2 votes free, since I haven't been tracking these things for a while.) Though it's unlikely Sun will suddenly decide to fix this now, just before 1.5.0 goes public. We may have to wait a few more years for this one.


"I'm not back." - Bill Harding, Twister
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

Thanks, Jim, for confirming that something's rotten in Denmark.

I can call setAccessible() and I think that it will generally succeed when it's supposed to, so that's not so bad.

Can't ask the author to expose the class because it's not one particular class; it's actually something that comes up from time to time when people use the Jess scripting language's reflection support. There's a much more common case where the public method in a package-protected class is actually a method that implements an interface. The workaround there is to walk the class hierarchy and retrieve the Method object from the Class that represents the interface itself; that one will be accessible. Much more rarely, though, this version of the problem comes up, and I've never had a good solution other than calling setAccessible(), which I've been loath to do. Going to bite the bullet now, though.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Reflection access rules