[armedbear-devel] new jcall / jar:file: path functions

Alessio Stalla alessiostalla at gmail.com
Thu Jan 7 15:32:59 UTC 2010


On Thu, Jan 7, 2010 at 6:39 AM, Alan Ruttenberg
<alanruttenberg at 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




More information about the armedbear-devel mailing list