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?
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.