⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 appendb.htm

📁 java书籍《thinking in java》
💻 HTM
📖 第 1 页 / 共 3 页
字号:
    app.changeObject(anObj);
    System.out.println(<font color=#004488>"Java: "</font> + anObj.aValue);
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">After compiling the code and running
<B>javah</B>, you can implement the native method. In the example below, once
the field and method ID are obtained, they are accessed through JNI functions.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXB_I21' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXB_I22>
</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: appendixb:UseObjImpl.cpp</font>
<font color=#009900>//# Tested with VC++ &amp; BC++. Include path must </font>
<font color=#009900>//# be adjusted to find the JNI headers. See </font>
<font color=#009900>//# the makefile for this chapter (in the </font>
<font color=#009900>//# downloadable source code) for an example.</font>
#include &lt;jni.h&gt;
extern <font color=#004488>"C"</font> JNIEXPORT <font color=#0000ff>void</font> JNICALL
Java_UseObjects_changeObject(
JNIEnv* env, jobject, jobject obj) {
  jclass cls = env-&gt;GetObjectClass(obj);
  jfieldID fid = env-&gt;GetFieldID(
    cls, <font color=#004488>"aValue"</font>, <font color=#004488>"I"</font>);
  jmethodID mid = env-&gt;GetMethodID(
    cls, <font color=#004488>"divByTwo"</font>, <font color=#004488>"()V"</font>);
  <font color=#0000ff>int</font> value = env-&gt;GetIntField(obj, fid);
  printf(<font color=#004488>"Native: %d\n"</font>, value);
  env-&gt;SetIntField(obj, fid, 6);
  env-&gt;CallVoidMethod(obj, mid);
  value = env-&gt;GetIntField(obj, fid);
  printf(<font color=#004488>"Native: %d\n"</font>, value);
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Ignoring the &#8220;this&#8221;
equivalent, the C++ function receives a <B>jobject</B>, which is the native side
of the Java object reference we pass from the Java code. We simply read
<B>aValue</B>, print it out, change the value, call the object&#8217;s
<B>divByTwo(&#160;)</B> method, and print the value out again. 

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXB_I22' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXB_I23>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To access a Java field or method, you
must first obtain its identifier using <B>GetFieldID(&#160;)</B> for fields and
<B>GetMethodID(&#160;)</B> for methods. These functions take the class object, a
string containing the element name, and a string that gives type information:
the data type of the field, or signature information for a method (details can
be found in the JNI documentation). These functions return an identifier that
you use to access the element. This approach might seem convoluted, but your
native method has no knowledge of the internal layout of the Java object.
Instead, it must access fields and methods through indexes returned by the JVM.
This allows different JVMs to implement different internal object layouts with
no impact on your native methods.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXB_I23' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXB_I24>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you run the Java program, you&#8217;ll
see that the object that&#8217;s passed from the Java side is manipulated by
your native method. But what exactly is passed? A pointer or a Java reference?
And what is the garbage collector doing during native method calls?

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXB_I24' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXB_I25>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <A NAME="Index2292"></A>garbage
collector continues to operate during native method execution, but it&#8217;s
guaranteed that your objects will not be garbage-collected during a native
method call. To ensure this, <I>local references</I> are created before, and
destroyed right after, the native method call. Since their lifetime wraps the
call, you know that the objects will be valid throughout the native method call.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXB_I25' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXB_I26>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Since these references are created and
subsequently destroyed every time the function is called, you cannot make local
copies in your native methods, in <B>static</B> variables. If you want a
reference that lasts across function invocations, you need a global reference.
Global references are not created by the JVM, but the programmer can make a
global reference out of a local one by calling specific JNI functions. When you
create a global reference, you become responsible for the lifetime of the
referenced object. The global reference (and the object it refers to) will be in
memory until the programmer explicitly frees the reference with the appropriate
JNI function. It&#8217;s similar to <B>malloc(&#160;)</B> and
<B>free(&#160;)</B> in C.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXB_I26' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXB_I27>
</FONT><A NAME="_Toc481064955"></A><BR></P></DIV>
<A NAME="Heading636"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
JNI and Java exceptions</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">With <A NAME="Index2293"></A>JNI, Java
exceptions can be thrown, caught, printed, and rethrown just as they are inside
a Java program. But it&#8217;s up to the programmer to call dedicated JNI
functions to deal with exceptions. Here are the JNI functions for exception
handling: 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXB_I27' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXB_I28>
</FONT><BR></P></DIV>
<UL>
<LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia"><B>Throw(&#160;)</B></FONT><BR><FONT FACE="Georgia">Throws
an existing exception object. Used in native methods to rethrow an
exception.</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia"><B>ThrowNew(&#160;)</B></FONT><BR><FONT FACE="Georgia">Generates
a new exception object and throws
it.</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia"><B>ExceptionOccurred(&#160;)</B></FONT><BR><FONT FACE="Georgia">Determines
if an exception was thrown and not yet
cleared.</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia"><B>ExceptionDescribe(&#160;)</B></FONT><BR><FONT FACE="Georgia">Prints
an exception and the stack
trace.</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia"><B>ExceptionClear(&#160;)</B></FONT><BR><FONT FACE="Georgia">Clears
a pending
exception.</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia"><B>FatalError(&#160;)</B></FONT><BR><FONT FACE="Georgia">Raises
a fatal error. Does not
return.</FONT></UL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Among these, you
can&#8217;t ignore <B>ExceptionOccurred(&#160;)</B> and
<B>ExceptionClear(&#160;)</B>. Most JNI functions can generate exceptions, and
there is no language feature that you can use in place of a Java try block, so
you must call <B>ExceptionOccurred(&#160;) </B>after each JNI function call to
see if an exception was thrown. If you detect an exception, you may choose to
handle it (and possibly rethrow it). You must make certain, however, that the
exception is eventually cleared. This can be done in your function using
<B>ExceptionClear(&#160;)</B> or in some other function if the exception is
rethrown, but it must be done.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXB_I28' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXB_I29>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You must ensure that the exception is
cleared, because otherwise the results will be unpredictable if you call a JNI
function while an exception is pending. There are few JNI functions that are
safe to call during an exception; among these, of course, are all the exception
handling functions.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXB_I29' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXB_I30>
</FONT><A NAME="_Toc481064956"></A><BR></P></DIV>
<A NAME="Heading637"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
JNI and threading</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Since Java is a multithreaded language,
several threads can call a native method concurrently. (The native method might
be suspended in the middle of its operation when a second thread calls it.)
It&#8217;s entirely up to the programmer to guarantee that the native call is
thread-safe; i.e., it does not modify shared data in an unmonitored way.
Basically, you have two options: declare the native method as
<B>synchronized</B>, or implement some other strategy within the native method
to ensure correct, concurrent data manipulation.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXB_I30' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXB_I31>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Also, you should never pass the
<B>JNIEnv</B> pointer across threads, since the internal structure it points to
is allocated on a per-thread basis and contains information that makes sense
only in that particular thread.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXB_I31' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXB_I32>
</FONT><A NAME="_Toc481064957"></A><BR></P></DIV>
<A NAME="Heading638"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Using a preexisting code base</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The easiest way to implement JNI native
methods is to start writing native method prototypes in a Java class, compile
that class, and run the <B>.class</B> file through <B>javah</B>. But what if you
have a large, preexisting code base that you want to call from Java? Renaming
all the functions in your DLLs to match the JNI name mangling convention is not
a viable solution. The best approach is to write a wrapper DLL
&#8220;outside&#8221; your original code base. The Java code calls functions in
this new DLL, which in turn calls your original DLL functions. This solution is
not just a work-around; in most cases you must do this anyway because you must
call JNI functions on the object references before you can use them.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXB_I32' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXB_I33>
</FONT><A NAME="_Toc481064958"></A><BR></P></DIV>
<A NAME="Heading639"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Additional information</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can find further introductory
material, including a C (rather than C++) example and discussion of Microsoft
issues, in Appendix A of the first edition of this book, which can be found on
the CD ROM bound in with this book, or in a free download from
<I>www.BruceEckel.com</I>. More extensive information is available at
<I>java.sun.com</I> (in the search engine, select &#8220;training &amp;
tutorials&#8221; for keywords &#8220;native methods&#8221;). Chapter 11 of
<I>Core Java 2</I>, <I>Volume II</I>, by Horstmann &amp; Cornell (Prentice-Hall,
2000) gives excellent coverage of native methods. 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXB_I33' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

</FONT><BR></P></DIV>
<DIV ALIGN="CENTER">
    <FONT FACE="Verdana" size = "-1">
     [ <a href="AppendA.htm">Previous Chapter</a> ] 
    [ <a href="SimpCont.htm">Short TOC</a> ] 
    [ <a href="Contents.htm">Table of Contents</a> ] 
    [ <a href="DocIdx.htm">Index</a> ]
     [ <a href="AppendC.htm">Next Chapter</a> ] 
    </FONT>
    <BR>
 Last Update:05/21/2001</P></DIV>

</BODY>

</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -