Chas Emerick
unread,Aug 20, 2008, 4:06:08 PM8/20/08Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to Clojure
I'm back to wading in unfamiliar waters (java bytecode). In the
process of using some bytecode verification tools on a couple of
classes emitted by genclass (we're using r994 at the moment), I
stumbled across a couple of errors related to references in the
genclass classfiles to IFn.invoke with nonexistent arities
(specifically, it looks like the genclass class is attempting to call
21- and 22-argument overloads of IFn.invoke).
Here's a simple testcase; the gen-class specification is this:
(gen-and-save-class "/" 'Test :implements clojure.lang.IFn)
And the errors I'm getting include:
---------
Warning: Test: can't find referenced method 'java.lang.Object
invoke(java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object)'
in class clojure.lang.IFn
Warning: Test: can't find referenced method 'java.lang.Object
invoke(java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object)'
in class clojure.lang.IFn
---------
Looking at the bytecode (in jclasslib, which is very helpful with this
sort of thing), it looks like the 19- and 20-arg overloads of
IFn.invoke are attempting to call 21- and 22-arg clojure
implementations of invoke. (One of the extra arguments being the
object being called -- not sure what the other extra argument is,
though.) To confirm this, I did this in the REPL:
com=> (in-ns 'com)
#<Namespace: com>
com=> (gen-and-load-class 'com.Test :implements [clojure.lang.IFn])
com=> (.invoke (com.Test.) 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1) ;
20-arg invocation
java.lang.NoSuchMethodError: clojure.lang.IFn.invoke(Ljava/lang/
Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/
lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/
Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/
lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/
Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/
lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
at com.Test.invoke(Unknown Source)
at com.eval__2449.invoke(Unknown Source)
at clojure.lang.Compiler.eval(Compiler.java:3847)
I'm not sure what the best solution is to this problem. It's probably
enough to always toss an UnsupportedOperationException rather than
attempt to marshal arguments for any method that has more than 18
arguments (perhaps this is best done in the emit-forwarding-method fn
implementation in genclass?). I'm sufficiently unsure of that idea
that I've not yet attempted a patch, as it's entirely possible that
there's a more elegant way around this (although the current 20-arg
limit on IFn and the way clojure method implementations are invoked
with 'this', etc., would seem to make anything else require some not-
insignificant redesign).
Thoughts?
Thanks,
- Chas