Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 3 of 4
JObject::isNull(): /**
* @param jstring - A java.lang.String
*/
JNIEXPORT void JNICALL Java_foo_Bar_someMethod( JNIEnv *env, jstring
javaString ) {
String str( javaString );
if ( str.isNull() ) {
cout << "Error - The argument, javaString, must not be
null." << endl;
}
}
Both the Throwable and String C++ proxy classes derive from JObject (as do all reference-type proxy classes). These classes are included (along with a few others) as a core part of the Jace
library to provide users with a tighter integration between the C++ and Java languages. (I discuss this in more detail in
the "C++ Integration" section.)
Jace sports several features, including thread management, exception management, and automatic type conversions, among others. Let's examine those features and more.
In JNI, a few thread issues exist:
Jace addresses all these issues. First, every function in the Jace library automatically retrieves a JNIEnv pointer that is valid for the current thread.
Second, Jace creates global references to the necessary JNI types. For example, upon construction, a JClass creates a global reference to its jclass member, and a JObject creates a global reference to its jobject member. Unlike local references, which are only valid for the current thread, global references are valid across all threads.
Finally, every function in Jace ensures that the current thread is attached to the JVM before calling any JNI functions.
Exception handling is one bane of JNI programming. Jace has two policies for exception handling:
JNIException.
using namespace jace::java::net;
void readGoogle() {
try {
/* When Jace internally executes NewObject, it checks to
* see if an exception is thrown. If the JNI function
* ExceptionOccurred, returns an exception, Jace clears the
* exception, creates a corresponding C++ proxy, and throws it.
*/
URL url( "http://www.google.com" );
}
/* Here, you catch the Jace thrown C++ proxy exception.
*/
catch ( MalformedURLException& e ) {
cout << e;
}
}
Jace provides automatic type conversions between C++ and Java primitive types. You may use a C++ std::string or char* anywhere a C++ proxy requires a java::lang::String. You may also use C++ types, like bool, int, and char, where C++ proxy methods require primitive JNI types, like JBoolean, JInt, and JChar:
using jace::javax::swing::JFrame;
JFrame createFrame( const std::string& title, int x, int y ) {
/* The prototype for JFrame is JFrame( java::lang::String str );.
* Jace automatically converts between std::string and java::lang::String.
*/
JFrame frame( title );
/* The prototype for setLocation is setLocation( JInt x, JInt y );.
* Jace automatically converts between int and JInt.
*/
frame.setLocation( x , y );
return frame;
}
Jace includes a C++ proxy-generating tool, BatchGen. The Jace community used BatchGen on the Java Runtime Environment (JRE)'s
rt.jar to generate the C++ proxy classes, which are included in the Jace C++ runtime library. However, the Jace community has modified
a few of those generated proxy classes for tighter integration with the C++ language and standard library.
java.lang.Object, for example, has an added operator<<( ostream& out, Object& object );, which lets you write any Object as you would using System.out.println().
java.lang.String has several added methods to integrate itself with std::strings and char*s, including operator+(), operator=(), and operator==().
The community has also modified java.lang.Throwable to derive from std::exception.
C++ proxy generation is the basis of type-safe access to Java objects. For any given Java classfile, Jace can generate a C++ proxy class that has all the same methods and fields. You call the C++ proxy methods in the same way you would call their Java counterparts. Fields are accessed through methods of the same name:
/* A Java class
*/
public class Foo {
public int aField;
public String aMethod( URL aURL );
}
/* You access the C++ proxy from C++
*/
Foo foo;
foo.aField() = 14;
String result = foo.aMethod( URL( "http://www.google.com" ) );
Jace provides two tools—ProxyGen and BatchGen—that you can use to generate C++ proxy classes from Java classfiles. I describe these tools in this article's "Jace Tools" section.
You can use Jace's template JArray class to access Java arrays type-safely. Behind the scenes, Jace calls the appropriate Get<Type>ArrayElement() and Set<Type>ArrayElement() JNI functions as dictated by the array type:
JArray<JInt> intArray( 10 ); // Results in a call to NewIntArray int i = intArray[ 2 ]; // Results in a call to GetIntArrayElements JArray<String> stringArray( 5 ); // Results in a call to NewObjectArray std::string str = stringArray[ 2 ]; // Results in a call to GetObjectArrayElement
As mentioned previously, ProxyGen and BatchGen generate C++ proxy classes. ProxyGen generates the header and footer for a classfile. BatchGen generates the headers and footers for all classes in a jar file.
ProxyGen dumps the header file or source file for a Java classfile to standard output. ProxyGen always includes public methods and fields in the generated C++ proxy class. Depending upon the access level specified, it will also include protected, package, or private fields and methods:
Usage: ProxyGenerator <class file> <header | source> [ options ]
Where options can be:
-protected : Generate protected fields and members
-package : Generate package fields and members
-private : Generate private fields and members
BatchGen is similar to ProxyGen in that it generates header and source files for C++ proxy classes. However, instead of reading from one Java classfile, BatchGen reads from a jar or zip file of multiple classfiles. Also, instead of writing the header and source files to standard output, BatchGen writes them to the specified destination directories: