Sei sulla pagina 1di 5

J D C

T E C H

T I P S
TIPS, TECHNIQUES, AND SAMPLE CODE

WELCOME to the Java Developer Connection(sm) (JDC) Tech Tips,


September 7, 1999. This issue covers:
* Error Checking With JNI
* Using JTextPane
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ERROR CHECKING WITH JNI
The Java(tm) Native Interface (JNI) is a mechanism that enables
Java to call functions written in other languages such as C++.
JNI supports the use of existing code libraries.
One important aspect of JNI is error handling. Consider the
following scenario. Suppose you have a Java application that passes
a string to a C++ function, and the string is further processed in
some way. The Java code looks like this:
public class err {
static {
System.loadLibrary("clib");
}
public static native void print(String s);
public static void main(String args[]) {
print("testing\n");
print(null);
}
}
In this example, print is a native method, that is, a method
coded in some other language. It accepts a string argument.
The implementation of this method is in a shared library, clib,
that is loaded using System.loadLibrary when the Java program
starts.
If you haven't used JNI before, you might wonder how to actually
build a JNI-based application. The first step is to compile the
Java program:
$ javac err.java
Then you specify:
$ javah -jni -o clib.cpp err
javah is a utility program that comes with the JDK(tm) software.
It generates a C++ function prototype for the native method
(function) found in the example above. In other words, if you have
a Java program that calls a native function, you need to create
a shared library containing a C++ implementation of that function.
The function in the library needs to have a specific name or
signature.

The implementation of the native function looks like this:


// clib.cpp
#include <stdio.h>
#include <jni.h>
extern "C" {
JNIEXPORT void JNICALL
Java_err_print(JNIEnv* env, jclass c, jstring s) {
if (s == NULL) {
jclass exc =
env->FindClass("java/lang/NullPointerException");
if (exc != NULL)
env->ThrowNew(exc, "(in C++ code)");
return;
}
const jbyte* str = env->GetStringUTFChars(s, NULL);
if (str == NULL)
return;
printf("%s", str);
env->ReleaseStringUTFChars(s, str);
}
}
The 'extern "C"' is a C++ notation saying that the function should
have a C external name instead of a C++ one. C++ compilers vary in
the way they generate function names, due to differences in encoding
of overloaded argument lists and so on. The function needs to have
a C external name to ensure name consistency.
The sequence for building a shared library varies. For example,
using Borland C++Builder 4, you specify:
$ bcc32 -c -Ic:/java/include -Ic:/java/include/win32 clib.cpp
$ bcc32 -tWD clib.obj
where c:/java is the directory where the Java(tm) 2 SDK is installed.
Once you've built the shared library, the program is run as usual:
$ java err
There are several interesting aspects of the C++ function worth
mentioning. One is that C++ doesn't automatically check for
null pointers (references) in the way that the Java language does.
If you pass a null string to the function and don't check for it,
you'll probably get a "Segmentation violation" error.
So you must check whether the passed-in pointer is null.
If it is, an exception is raised using the JNI ThrowNew function.
This doesn't immediately trigger the exception, but propagates it
to the calling Java program. The Java program treats it as a normal
exception originating in Java code.
Once the pointer is checked, the program retrieves the
passed-in string. Low-level C/C++ strings and Java strings are
represented differently. Because of this, a JNI call is used to

retrieve a pointer to the string characters. The string is in UTF-8


format, which is equivalent to 7-bit ASCII if (and only if) the
string is composed entirely of 7-bit characters. Once the pointer
is retrieved, the string can be printed using printf.
Here's another point about error handling. GetStringUTFChars
returns NULL if it cannot allocate space to copy
the string. If this JNI function does return NULL, then it has
already raised a java.lang.OutOfMemoryError exception which will
be propagated back to the Java program. In this case, there's no
need to detect a NULL return value and raise an exception yourself.
Let's run the program. The output is:
testing
Exception in thread "main" java.lang.NullPointerException:
(in C++ code)
at err.print(Native Method)
at err.main(err.java:8)
The book "The Java Native Interface" by Sheng Liang covers the JNI
in depth. For information about this book, see
http://java.sun.com/docs/books/jni/index.html
USING JTEXTPANE
The Java(tm) Foundation Classes (JFC) Project Swing classes
JTextArea and JTextField are used as GUI components for text entry
and text display. JEditorPane and JTextPane are also used for plain
text, but they go further. You can use them for styled text, HTML,
and RTF, or to insert arbitrary images and components into the pane.
JEditorPane is a subclass of JTextComponent, and you can use it
to edit various kinds of content based on an "editor kit".
An editor kit is a class that contains functions for text handling.
For example, you can use it to perform standard text editor actions
(such as, cut/copy/paste), or read text documents from a file.
JTextPane is a subclass of JEditorPane, combined with
StyledEditorKit. It allows you to edit styled text. Examples of
styled text include underlining, italicized text, and inclusion of
images and components in the text.
One application of JTextPane might be in a customized word
processor, in particular, where you want special symbols to mark
the text. Here is an example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class MyComponent extends JComponent {
public Dimension getPreferredSize() {
return new Dimension(10, 15);
}
public Dimension getMaximumSize() {
return getPreferredSize();
}
public void paint(Graphics g) {
Dimension d = getSize();
g.setColor(Color.red);

g.fillRect(0, 0, d.width, d.height);


}
}
public class panedemo {
public static void main(String args[]) {
JFrame frame = new JFrame("JTextPane demo");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
final JTextPane pane = new JTextPane();
pane.setPreferredSize(new Dimension(600, 400));
JButton insbutton = new JButton("Insert Component");
insbutton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
pane.insertComponent(new MyComponent());
pane.requestFocus();
}
});
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add("North", insbutton);
panel.add("Center", pane);
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
This example sets up a JTextPane area, where you can enter text
in a normal way. If you click on "Insert Component", an instance
of a custom component is inserted into the text. In this example,
the component is an instance of MyComponent. The component consists
of a 10 x 15 red filled box, representing markup that you'd like
to insert into the text. In other words, you can insert arbitrary
components interspersed with text.
You can also use the InsertIcon method to insert images into the
text pane.
Note: JDK 1.2.2 fixes a number of bugs, some of them associated
with the use of JFC Swing. If you have trouble running the
JTextPane example (or any other code that includes JFC Swing
components), try running it with JDK 1.2.2.
. . . . . . . . . . . . . . . . . . . . . . . .
- NOTE
The names on the JDC mailing list are used for internal Sun
Microsystems(tm) purposes only. To remove your name from the list,
see Subscribe/Unsubscribe below.

- FEEDBACK
Comments? Send your feedback on the JDC Tech Tips to:
jdc-webmaster
- SUBSCRIBE/UNSUBSCRIBE
The JDC Tech Tips are sent to you because you elected to subscribe
when you registered as a JDC member. To unsubscribe from JDC Email,
go to the following address and enter the email address you wish to
remove from the mailing list:
http://developer.java.sun.com/unsubscribe.html
To become a JDC member and subscribe to this newsletter go to:
http://java.sun.com/jdc/
- ARCHIVES
You'll find the JDC Tech Tips archives at:
http://developer.java.sun.com/developer/TechTips/index.html
- COPYRIGHT
Copyright 1999 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA.
This document is protected by copyright. For more information, see:
http://developer.java.sun.com/developer/copyright.html
This issue of the JDC Tech Tips is written by Glen McCluskey.
JDC Tech Tips
September 7, 1999

Potrebbero piacerti anche