Following up on this,
On Fri, Sep 21, 2012 at 4:39 PM, archisman rudra <archi.rudra@gmail.com> wrote:Hi,
> Hi,
>
> hopefully this is the correct list. If not please let me know.
yes, you are writing to the correct list - welcome!
Interesting! I'm answering because I wrote the current (incomplete)
> Background:
> I am trying to use abcl to generate jars to send off to a hadoop cluster for
> execution.
version of jnew-runtime-class. Just FYI, you can find some notes about
it at <http://trac.common-lisp.net/armedbear/wiki/JavaFfi/RuntimeClass>.
This is a byproduct of the design - although the design is mine, and
> The svn version of the jnew-runtime-class does not store the
> actual method bodies in the generated class file, but rather loads the
> generated class file and sets the relevant field. Here is the relevant code
> :
>
> (multiple-value-bind (class-file method-implementation-fields)
> (apply #'java::%jnew-runtime-class class-name stream args)
> (sys::put-memory-function memory-class-loader
> class-name (sys::%get-output-stream-bytes
> stream))
> (let ((jclass (java:jcall "loadClass" memory-class-loader
> class-name)))
> (dolist (method method-implementation-fields)
> (setf (java:jfield jclass (car method)) (cdr method)))
> jclass))))
>
>
> This means that the generated jar file cannot be easily used from standard
> java code.
hasn't been discussed much among the other developers, so I'm not
representing anyone but myself. Let me clarify below.
What I wanted to achieve is to have methods that can be:
> I would like to add some code in the static initialization block
> of generated class file to do something equivalent. I will have to save the
> lambda expression for the method and have been experimenting as follows:
>
> (defvar *cf*)
> (defvar *mif*)
>
> (with-open-file (stream "test.class" :direction :output :element-type
> '(unsigned-byte 8))
> (multiple-value-bind (class-file method-implementation-field)
> (java::%jnew-runtime-class "test" stream :methods
> `(("forty_two_method1" :int () ,(lambda (this) 42))))
> (setf *cf* class-file)
> (setf *mif* method-implementation-field)))
>
> (with-open-file (stream "test_forms" :direction :output)
> (dolist (m *mif*)
> (system:dump-form (list (car m) (function-lambda-expression (cdr m)))
> stream)))
>
>
> This assumes that the lambda expression does not refer to any variable or
> user defined function, but perhaps the asdf-jar contrib might help here.
>
> I was going to write the relevant code and start using it for my project,
> but I was wondering if I am duplicating work that others have already done
> or are doing and whether there are other libraries (jffli perhaps, I am not
> very familiar with it) that have similar functionality. Also if there are
> other interactions with other parts of the system that I am perhaps missing.
>
> I would e grateful for any advice.
* arbitrary functions, including closures
* possibly redefined after the class has been loaded. Redefinition is
possible by using symbols as method implementations.
There's also a hidden goal that is to keep the implementation simple
enough, and compiling Lisp code to the body of methods in an arbitrary
class is not easy at the moment.
What explicitly is NOT a requirement is to have the generated class be
independent from ABCL (the methods are implemented in Lisp and will
always need runtime support). So, no matter how you arrange things,
you will never be able to distribute your class without abcl.jar. Note
that it is the same for Clojure, Scala, Groovy, etc.
I don't know specifically how Hadoop works, but, as I see things, you need to
1. provide abcl.jar + your class to it
2. have Hadoop execute enough code to load ABCL and initialize your class.
Now, probably the key point is who loads your class.
* if you can arrange to have ABCL load it and pass it to Hadoop, you
should be good with the current design.
* if Hadoop wants to load it by itself from a jar, then yes, you have
to somehow dump the method implementations somewhere and have the
class auto-load them from there when it is initialized.
For the second case, I propose an intermediate design that is, imho,
simpler than dumping arbitrary forms: special-case the situation when
a method implementation is a symbol. In that case, directly generate
an instruction in the class file to find that symbol in its package
and assign it to the appropriate field. If the implementation of a
method is not a symbol nothing changes. That way, you will still need
to init ABCL before loading your class, but, when all your method
implementations are symbols, the class will be able to initialize
itself without external support. If some methods are proper functions,
instead, the class won't be self-contained, but will need some Lisp
code to be executed to be properly initialized.
Does it make sense to you? Do you find it acceptable? If yes, I can
give a shot at implementing it, if you want.
Peace,
Alessio
--
Some gratuitous spam:
http://ripple-project.org Ripple, social credit system
http://villages.cc Villages.cc, Ripple-powered community economy
http://common-lisp.net/project/armedbear ABCL, Common Lisp on the JVM
http://code.google.com/p/tapulli my current open source projects
http://www.manydesigns.com/ ManyDesigns Portofino, open source
model-driven Java web application framework