On Thu, Jan 7, 2010 at 6:39 AM, Alan Ruttenberg alanruttenberg@gmail.com wrote:
I'm trying to use the new jcall code in place of jss calls. However I am getting an error I don't understand.
In the following:
(defun directory-in-jar (pathname) (let* ((jarfile (subseq (namestring (pathname-device pathname)) 9)) (rest-pathname (namestring (make-pathname :directory (pathname-directory pathname) :name (pathname-name pathname) :type (pathname-type pathname))))) (if (or (position #* (namestring rest-pathname)) (wild-pathname-p rest-pathname)) (let ((jar (jnew "java.util.zip.ZipFile" jarfile))) (let ((els (jcall "entries" jar))) (loop while (#"hasMoreElements" els) for name = (jcall "getName" (#"nextElement" els)) when (pathname-match-p (concatenate 'string "/" name) rest-pathname) collect (make-pathname :device (pathname-device pathname) :name (pathname-name name) :type (pathname-type name) :directory `(:absolute ,@(cdr (pathname-directory name))))))) (let ((truename (probe-file-in-jar pathname))) (if truename (list truename) nil)))))
If I replace the call (#"hasMoreElements" els) with (jcall "hasMoreElements" els) I get the error:
java.lang.IllegalAccessException: Class org.armedbear.lisp.Java can not access a member of class java.util.zip.ZipFile$3 with modifiers "public" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65) at java.lang.reflect.Method.invoke(Method.java:583) at org.armedbear.lisp.Java.jcall(Java.java:660) ...
If I replace the call (#"nextElement" els) with (jcall "nextElement" els) I get the error
java.lang.IllegalAccessException: Class org.armedbear.lisp.Java can not access a member of class java.util.zip.ZipFile$3 with modifiers "public volatile" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65) at java.lang.reflect.Method.invoke(Method.java:583) at org.armedbear.lisp.Java.jcall(Java.java:660)
This from http://svn.mumble.net:8080/svn/lsw/trunk/patches/jarfile.lisp where I'm starting to add more path functions that work with the jar:file: pathname scheme. Feel free to steal and incorporate into abcl.
This code fails too with the same error:
(let ((jar (jnew "java.util.zip.ZipFile" "/home/alessio/abcl/pippo.jar"))) (let ((els (jcall "entries" jar))) (let ((method (jmethod (jclass-of els) "hasMoreElements"))) (jcall method els))))
as does its translation to Java:
ZipFile jar = new ZipFile("/home/alessio/abcl/pippo.jar"); Object els = jar.entries(); Method method = els.getClass().getMethod("hasMoreElements"); method.invoke(els);
so it's some quirk of Java reflection that I'm not aware of. In fact, calling method.setAccessible(true); before invoking it removes the error. Maybe the inner classes ZipFile$x are not public, and that is sufficient to cause an IllegalAccessException? In any case, ABCL's jcall currently makes no attempts at ensuring the method is accessible before calling it.
hth, Alessio