Sourceforge Project
Public Forums


Basically, JPeerGen is a Javadoc doclet that can generate the code and header files for a compatible C++ peer class. The utility's intent is to make implementing native object oriented methods as smooth as possible. As a result, a binding layer will do its best to translate JNI types into native C++ types before passing them on to the native methods implementations. This same binding layer is responsible for doing reverse translations for Java methods that have been made available for calling from C++ code. The fileds that make up this binding layer are generated directly from the .java source file.

This image shows the basic high-level interaction between a Java object and its native peer.

Several files are generated to facilitate this interaction. These are as follows:

JNI header (.h) This is the file normally generated by javah and is required for the C part of the native method implementations. A user should rarely need to even look at this file.
JNI binding (.cpp) This is the implementation of the C functions defined in the JNI header file. The functions simply lookup the C++ peer instance and forward the call onto the relevant C++ binding method.
C++ binding (.h) This is included in the peer header file and defines the forward and reverse call bindings between JNI and C++. JNI calls have their parameters translated to native C++ types when possible. The return values are translated back to JNI types when possible.
Any reverse-peered Java methods are bound in a similar way by translating the C++ parameters to JNI types. The return values are translated back to C++ types.
Peer header (.h) This file sets up the necessary includes for using the peered class but is otherwise user editable. It's primarily used to make the user's life easier.
By default, this file is not overwritten when JPeerGen is run again.
Peer class (.cpp) This file sets up empty method stubs for any of the native peered methods. This helps the user hit the ground running as well as give the user an idea of what parameters were able to be translated and which ones weren't.
By default, this file is not overwritten when JPeerGen is run again. Instead, a .new file is created that the user can use to cut and paste any new or modified method signatures since the last time JPeerGen was run.

Following is an example list of files that might be generated for the class foo.MyObject:

  • foo_MyObject.h (JNI header)
  • foo_MyObjectJniBinding.cpp (JNI binding)
  • MyObjectBindings.h (C++ binding)
  • MyObjectPeer.h (Peer header)
  • MyObjectPeer.cpp (Peer class)
This diagram illustrates the interaction between these files:

Best Usage Patterns

It is important to note that the binding interaction is not free. In addition to the normal JNI overhead, JPeerGen adds some casting and one or two extra calls in the chain. Furthermore, a current limitation of the system is that C++ objects are not cleaned up properly when the Java object is garbage collected. (Though, users can implement this manually with a native terminate method.)

This means that JPeerGen is best used in coarse-grained situations like native services or other facade-like objects. These are both long-lived and usually do enough work on their own to justify the small bits of call overhead that are added.

Future Improvements

On the books is better handling for array types and the ability for cross-peered objects to be automatically converted.

Currently, the generator can only pass array types down as jobjects. This is something I'd like to add despite the overhead the array copying would cause. It's just to convenient to ignore.

Also, right now the only peered object that can be auto-converted is the one for which the generator is currently running. So if a native method on MyObject takes a MyObject instance as a parameter, it will be automitcally converted to the MyObjectPeer on the C++ side. However, if a native method on MyObject takes a MyOtherObject instance as a parameter, it will not be converted even if MyOtherObject is also a peered object. JPeerGen already knows about all of the classes that were passed to the doclet, so this should be a trivial enough change. However, the type conversion code needs a major refactoring first so this will have to wait for the 2.0 cycle.

Copyright Paul Speed and Progeeks 2004