• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Liutauras Vilda
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
Bartenders:

Reflection access rules

 
author and iconoclast
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
Sheriff
Posts: 7023
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Did you intend for Sub to extend Base?
 
Ernest Friedman-Hill
author and iconoclast
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes, thanks. I edited my post to reflect Dirk's comment.
[ September 10, 2004: Message edited by: Ernest Friedman-Hill ]
 
Ranch Hand
Posts: 1873
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Ernest,

How did you fixed it? Made the Base public?

Thanks
Maulin
 
Ernest Friedman-Hill
author and iconoclast
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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.
 
author
Posts: 11962
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
For me, the following works just fine:

Do you have some kind of a sadistic java.lang.SecurityManager implementation in use?
 
Maulin Vasavada
Ranch Hand
Posts: 1873
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 1873
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I guess its an incosistency between JVM Impl and Reflection Impl

Thinking if there is some way out...

Thanks
Maulin
 
Maulin Vasavada
Ranch Hand
Posts: 1873
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 1873
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
[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.
 
Ernest Friedman-Hill
author and iconoclast
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Clowns were never meant to be THAT big! We must destroy it with this tiny ad:
New web page for Paul's Rocket Mass Heaters movies
https://coderanch.com/t/785239/web-page-Paul-Rocket-Mass
reply
    Bookmark Topic Watch Topic
  • New Topic