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 ]
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.
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
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: 1863
posted
0
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: 1863
posted
0
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: 1863
posted
0
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: 18652
posted
0
[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):
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
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.