On Wed, Mar 17, 2010 at 12:06 AM, David Kirkman dkirkman@ucsd.edu wrote:
Does anybody know of a good way to serialize lisp objects into java byte arrays? I've got a method that almost works, but if anybody has a better/canonical way of doing this I'd love to know!
I've been trying to use cl-store, outputting to a stream I create with sys::%make-byte-array-output-stream, and then getting the byte array with sys::%get-output-stream-bytes. I've only been using abcl for a few days, and I found those functions by grepping through the sources, so I apologize if I'm inviting trouble by messing around with functions you never meant users to play with.
Anyway, the output works fine. But I can't find the equivalent of sys::%make-byte-array-output-stream to create an input stream, so I attempted to make my own
(defun make-byte-array-input-stream (bytes) (let ((bis (jnew (jconstructor "java.io.ByteArrayInputStream" "[B") bytes))) (jnew (jconstructor "org.armedbear.lisp.Stream" "java.io.InputStream") bis)))
This almost seems to work, but if I try to use it I get a java exception and a (very long) java stack trace. I put a copy of the stack trace at the end of this message. Here is an expression which will produce the problem in abcl-18.1
(let ((outbytes (with-open-stream (stream (sys::%make-byte-array-output-stream)) (write-byte 101 stream) (sys::%get-output-stream-bytes stream)))) ;; now open the byte array as an input stream (with-open-stream (stream (make-byte-array-input-stream outbytes)) ;; all works fine until here (read-byte stream)))
I don't need to read the stream, asking for the element type of the input stream is enough to cause trouble ...
(let ((outbytes (with-open-stream (stream (sys::%make-byte-array-output-stream)) (write-byte 101 stream) (sys::%get-output-stream-bytes stream)))) (with-open-stream (stream (make-byte-array-input-stream outbytes)) (stream-element-type stream)))
I can fix the problem and make my code work, but I have to change Stream.java to make it work. I added
elementType = UNSIGNED_BYTE_8;
to the initAsBinaryInputStream(InputStream in) method. I did this because the stack trace suggested that the problem was stream_element_type.execute() was returning null.
Anyway, that fixes the problem, and I'm happily serializing/deserializing lisp objects to a Berkeley DB ... so I guess I'm happy! But I don't know how rational that fix is, because I don't really know how Stream is supposed to work. I suspect that my 'fix' probably breaks something else that I'm just not using yet.
Any ideas?
I wrote sys::%make-byte-array-output-stream in order to make the runtime compiler capable of generating bytecode without using temporary files; it wasn't meant to be used by the ABCL user, and as such it's not very polished (for example, the type of a byte-array-output-stream is simply STREAM). In any case, it's defined in the ByteArrayOutputStream Java class, and as you correctly noted, it explicitly sets the element type to (unsigned-byte 8). As a quick and dirty solution, you could more or less copy-paste that class and replace "output" with "input" :) (as well as update Autoload.java to make ABCL know of the new primitives).
We should probably polish it a bit and release it as an extension.
Alessio
Thanks,
-david k.
Here's the first few lines of the stack trace ...
CL-USER(2): Debugger invoked on condition of type SIMPLE-TYPE-ERROR: java.lang.NullPointerException at org.armedbear.lisp.Primitives$49.execute(Primitives.java:795) at org.armedbear.lisp.Symbol.execute(Symbol.java:781) at org.armedbear.lisp.LispThread.execute(LispThread.java:579) at org.armedbear.lisp.print_8.execute(print.lisp:127) at org.armedbear.lisp.Symbol.execute(Symbol.java:781) at org.armedbear.lisp.LispThread.execute(LispThread.java:579) at org.armedbear.lisp.print_14.execute(print.lisp:279)
... (and it ends with)
at org.armedbear.lisp.AutoloadedFunctionProxy.execute(AutoloadedFunctionProxy.java:139) at org.armedbear.lisp.Symbol.execute(Symbol.java:760) at org.armedbear.lisp.LispThread.execute(LispThread.java:546) at org.armedbear.lisp.top_level_51.execute(top-level.lisp:415) at org.armedbear.lisp.AutoloadedFunctionProxy.execute(AutoloadedFunctionProxy.java:139) at org.armedbear.lisp.LispThread.execute(LispThread.java:546) at org.armedbear.lisp.Interpreter.run(Interpreter.java:310) at org.armedbear.lisp.Main$1.run(Main.java:50) at java.lang.Thread.run(Thread.java:613) READ-BYTE: unsupported element type Debugger invoked on condition of type ERROR: Caught java.lang.NullPointerException. Restarts: 0: TOP-LEVEL Return to top level.
armedbear-devel mailing list armedbear-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/armedbear-devel