July 30, 2009 at 10:35 pm
· Filed under Clojure
Sometimes, one wants to write a Clojure macro to assist in Java interoperability, where the object types are determined by the arguments to the macro. In this situation, the normal strategy of using a #^class type hint doesn’t work, since the class isn’t known at read time. Here’s a very contrived example, where the macro declare-first-char defines a function first-char, which calls the (.charAt % 0) method on its argument. The class for the type hint is passed as an argument to the macro.
user> (set! *warn-on-reflection* true)
true
user> (defmacro declare-first-char [cls]
(let [x (gensym)]
`(defn first-char [~(with-meta x {:tag cls})]
(.charAt ~x 0))))
#'user/declare-first-char
user> (declare-first-char String)
#'user/first-char ; No reflection warning!
user> (first-char "test")
\t
The key here is the [~(with-meta x {:tag cls})] fragment, which replaces the normal [#^String x#] version that could be used if the type was known in advance.
Permalink
May 28, 2009 at 11:06 pm
· Filed under Java, Programming
I just finished writing a Java wrapper for a complex C++ library, and had a fair bit of trouble finding solutions to (or even basic documentation pertaining to) some of the problems that came up.
Things seem pretty easy if you just need to call some C++ functions from Java: you use JNI and do a little gruntwork to translate data to and from Java objects, or let SWIG do the heavy lifting for you. However, in my case things were harder, because the library is multithreaded (using boost threads) and makes heavy use of callbacks into the client (i.e., Java).
The main complication is that each native thread that calls a Java method must do so through its own JNIEnv pointer, obtained by calling AttachCurrentThread on a JavaVM instance. Each such native thread (which may be created and managed by code you can’t change) must eventually be detached from the JVM by calling DetachCurrentThread within it, or it seems memory leaks and JVM shutdown issues can result. There is no obvious way to detach the thread from the outside, so if you let the thread die or get away before it calls DetachCurrentThread you’re stuck.
Since a C++ wrapper for the Java callbacks is needed anyway, one easy solution is to attach before each callback and detach afterwards. However, this may be very expensive; I haven’t measured the cost, but one post I found quoted a factor of 6 slowdown. My alternative solution uses boost::thread_specific_ptr to detach each native thread just before it dies:
#include <boost/thread/tss.hpp>
static JavaVM *vm = NULL;
class ThreadJNIEnv {
public:
bool _detach;
JNIEnv *env;
ThreadJNIEnv() {
cout << "Attaching " << boost::this_thread::get_id() << endl;
vm->AttachCurrentThread((void **) &env, NULL);
ASSERT(env != NULL);
_detach = true;
}
ThreadJNIEnv(JNIEnv *e) {
env = e;
_detach = false;
}
~ThreadJNIEnv() {
if (_detach) {
cout << "Detaching " << boost::this_thread::get_id() << endl;
vm->DetachCurrentThread();
}
}
};
static boost::thread_specific_ptr<ThreadJNIEnv> envs;
JNIEnv *getJNIEnv(){
ThreadJNIEnv *tenv = envs.get();
if (tenv == NULL) {
tenv = new ThreadJNIEnv();
envs.reset(tenv);
}
return tenv->env;
}
bool init(JNIEnv *env) {
if (!env->GetJavaVM(&vm) < 0) return false;
envs.reset(new ThreadJNIEnv(env));
return true;
}
If your main function is in Java, you initialize the library by calling init(env) with the current thread’s JNIEnv (with multiple Java threads, you may have to take care). If it’s C++, you just set “vm” directly when you create the JVM instance.
Then, any function not in a direct JNI call just uses getJNIEnv() to get a JNIEnv pointer that’s valid for the current thread. This will work correctly both for indirect calls from Java, and from native threads, which will be automatically attached on the first call to getJNIEnv and automatically detached before death.
Seemed to work for me on Ubuntu; YMMV.
Permalink
April 9, 2009 at 3:47 pm
· Filed under Clojure
Debugging and profiling Clojure code with multimethods can be a pain, since methods show up as anonymous functions in stack traces and profile results. When you’re debugging you at least get a line number, but if you’ve loaded your code in a nonstandard way (i.e., with SLIME) or you’re using a profiler like YourKit, you don’t get this information. Then, the only clue you have to figure out what my.long.namespace$fn_12312 represents is context — who called it, and who it calls.
Similar issues exist for anonymous functions, which some time ago I realized you could give names by using (fn name [args] & body). What I didn’t realize is the same is true of multimethods. By simply using (defmethod multifn dispatch-val *name* [args] &body), you can give each instance of a multimethod a unique name, which will show up in stack traces and profile results.
Permalink