Reflector Bug

59 views
Skip to first unread message

Toralf Wittner

unread,
Dec 23, 2007, 7:56:56 PM12/23/07
to Clojure
The following code throws an Exception in the last line (. i (next)):

(def s (new java.util.HashSet))
(doto s (add 1) (add 2) (add 3))
(def i (. s (iterator)))
(if (. i (hasNext))
(. i (next)))

java.lang.IllegalAccessException: Class clojure.lang.Reflector can not
access a member of class java.util.HashMap$KeyIterator with modifiers
"public"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
at java.lang.reflect.Method.invoke(Method.java:588)
at
clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:98)
at
clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:26)
at clojure.lang.Compiler
$InstanceMethodExpr.eval(Compiler.java:845)
at clojure.lang.Compiler$IfExpr.eval(Compiler.java:1510)
at clojure.lang.Compiler.eval(Compiler.java:2640)
at clojure.lang.Compiler.load(Compiler.java:2765)
at clojure.lang.Compiler.loadFile(Compiler.java:2744)
at clojure.lang.RT$2.invoke(RT.java:144)
at clojure.lang.AFn.applyToHelper(AFn.java:158)
at clojure.lang.AFn.applyTo(AFn.java:149)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:1789)
at clojure.lang.Compiler.eval(Compiler.java:2640)
at clojure.lang.Repl.main(Repl.java:58)


This is because java.util.HashMap$KeyIterator is a private class which
inherits from the abstract class java.util.HashMap$HashIterator which
implements the iterator interface. The method next() is declared in the
Iterator interface but implemented in the private KeyIterator class. The
current clojure.lang.Reflector implementation does not check the
implemented interfaces of abstract superclasses and thus doesn't find
the right method to invoke. I have attached a patch that fixes this
problem.

Merry Christmas!

- Toralf

reflector.diff

Rich Hickey

unread,
Dec 27, 2007, 8:58:14 AM12/27/07
to Clojure
Thanks, I'll look at that.
> reflector.diff
> 2KDownload

Rich Hickey

unread,
Dec 28, 2007, 1:19:50 PM12/28/07
to Clojure


On Dec 23, 7:56 pm, Toralf Wittner <toralf.witt...@gmail.com> wrote:
> The following code throws an Exception in the last line (. i (next)):
>
> (def s (new java.util.HashSet))
> (doto s (add 1) (add 2) (add 3))
> (def i (. s (iterator)))
> (if (. i (hasNext))
> (. i (next)))
>
> java.lang.IllegalAccessException: Class clojure.lang.Reflector can not
> access a member of class java.util.HashMap$KeyIterator with modifiers
> "public"

> This is because java.util.HashMap$KeyIterator is a private class which
> inherits from the abstract class java.util.HashMap$HashIterator which
> implements the iterator interface. The method next() is declared in the
> Iterator interface but implemented in the private KeyIterator class. The
> current clojure.lang.Reflector implementation does not check the
> implemented interfaces of abstract superclasses and thus doesn't find
> the right method to invoke. I have attached a patch that fixes this
> problem.
>

I've put up a fix, but not your patch, since I don't think abstract-
ness enters into it. It's a full recursive search of superclasses and
interfaces for a public declaring class.

Thanks for the report!

Rich

Toralf Wittner

unread,
Dec 28, 2007, 4:07:04 PM12/28/07
to clo...@googlegroups.com
On Fri, 2007-12-28 at 10:19 -0800, Rich Hickey wrote:
> I've put up a fix, but not your patch, since I don't think abstract-
> ness enters into it. It's a full recursive search of superclasses and
> interfaces for a public declaring class.
>

Yes, you are right of course. My particular case was fixed by checking
for abstractness but in general a full search is the right thing to do.
Sorry for being imprecise.

Cheers,
Toralf


Reply all
Reply to author
Forward
0 new messages