In JNI, is there a more portable way than jlong to encapsulate a pointer?

You can use a hashtable to store pointers and return key of this hashtable to a user. Like:

 std::unordered_map<long, Foo*> handles;
 long newHandle = 0
 ...
  JNIEXPORT jlong JNICALL Java_Foo_create
  (JNIEnv *, jobject)
   {
       Foo* ptr = new Foo;
       long handle = newHandle;
       handles.insert(std::pair<long, Foo*>(newHandle++, ptr));
       return handle;
   }

Now you can use a handle to get pointer from the hashmap:

JNIEXPORT void JNICALL Java_Foo_use
  (JNIEnv *, jobject, jlong handle) {
   auto iter = handles.find(handle);
   if (iter != handles.end()) {
       Foo* ptr = iter->second;
       // use Foo* here
   }
}

Also this method will help you to check if an object was already deleted or to delete all Foo object that still exist. The drawbacks are that access to hashmap to get a pointer can decrease performance. Also you should probably guard with your handles map from multithread access or use thread-safe map implementation.

Alternatively, if you need to implement wrappers for Java, I would recommend to consider SWIG (Simplified Wrapper and Interface Generator).