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

📄 appendb.htm

📁 java书籍《thinking in java》
💻 HTM
📖 第 1 页 / 共 3 页
字号:
<backtalk:display ID=TIJ3_APPENDIXB_I9>
</FONT><A NAME="_Toc481064950"></A><BR></P></DIV>
<A NAME="Heading631"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Name mangling and function signatures</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">JNI imposes a naming convention (called
<I>name mangling</I>) on native methods. This is important, since it&#8217;s
part of the mechanism by which the virtual machine links Java calls to native
methods. Basically, all native methods start with the word &#8220;Java,&#8221;
followed by the name of the class in which the Java native declaration appears,
followed by the name of the Java method. The underscore character is used as a
separator. If the Java native method is overloaded, then the function signature
is appended to the name as well; you can see the native signature in the
comments preceding the prototype. For more information about name mangling and
native method signatures, please refer to the JNI documentation.

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

<backtalk:display ID=TIJ3_APPENDIXB_I10>
</FONT><A NAME="_Toc481064951"></A><BR></P></DIV>
<A NAME="Heading632"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Implementing your DLL</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">At this point, all you have to do is
write a C or C++ source code file that includes the <B>javah</B>-generated
header file and implements the native method, then compile it and generate a
dynamic link library. This part is platform-dependent. The code below is
compiled and linked into a file called <B>MsgImpl.dll</B> for Windows or
<B>MsgImpl.so</B> for Unix/Linux (the makefile packaged with the code listings
contains the commands to do this&#8212;it is available on the CD ROM bound into
this book, or as a free download from <I>www.BruceEckel.com</I>):

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

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

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: appendixb:MsgImpl.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;
#include &lt;stdio.h&gt;
#include <font color=#004488>"ShowMessage.h"</font>

extern <font color=#004488>"C"</font> JNIEXPORT <font color=#0000ff>void</font> JNICALL 
Java_ShowMessage_ShowMessage(JNIEnv* env, 
jobject, jstring jMsg) {
  <font color=#0000ff>const</font> <font color=#0000ff>char</font>* msg=env-&gt;GetStringUTFChars(jMsg,0);
  printf(<font color=#004488>"Thinking in Java, JNI: %s\n"</font>, msg);
  env-&gt;ReleaseStringUTFChars(jMsg, msg);
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The arguments that are passed into the
native method are the gateway back into Java. The first, of type
<B>JNIEnv</B>,<B> </B>contains all the hooks that allow you to call back into
the JVM. (We&#8217;ll look at this in the next section.) The second argument has
a different meaning depending on the type of method. For non-<B>static</B>
methods like the example above, the second argument is the equivalent of the
&#8220;this&#8221; pointer in C++ and similar to <B>this</B> in Java: it&#8217;s
a reference to the object that called the native method. For <B>static</B>
methods, it&#8217;s a reference to the <B>Class</B> object where the method is
implemented. 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_APPENDIXB_I11' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_APPENDIXB_I12>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The remaining arguments represent the
Java objects passed into the native method call. Primitives are also passed in
this way, but they come in by value.

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

<backtalk:display ID=TIJ3_APPENDIXB_I13>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In the following sections we&#8217;ll
explain this code by looking at the ways that you access and control the JVM
from inside a native method.

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

<backtalk:display ID=TIJ3_APPENDIXB_I14>
</FONT><A NAME="_Toc481064952"></A><BR></P></DIV>
<A NAME="Heading633"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Accessing JNI functions: <BR>the JNIEnv
argument<BR><A NAME="Index2290"></A><A NAME="Index2291"></A></H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">JNI functions are those that the
programmer uses to interact with the JVM from inside a native method. As you can
see in the example above, every JNI native method receives a special argument as
its first parameter: the <B>JNIEnv</B> argument, which is a pointer to a special
JNI data structure of type <B>JNIEnv_</B>. One element of the JNI data structure
is a pointer to an array generated by the JVM. Each element of this array is a
pointer to a JNI function. The JNI functions can be called from the native
method by dereferencing these pointers (it&#8217;s simpler than it sounds).
Every JVM provides its own implementation of the JNI functions, but their
addresses will always be at predefined offsets.

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

<backtalk:display ID=TIJ3_APPENDIXB_I15>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Through the <B>JNIEnv</B> argument, the
programmer has access to a large set of functions. These functions can be
grouped into the following categories:</FONT><BR></P></DIV>
<UL>
<LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Obtaining version
information</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Performing
class and object
operations</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Handling
global and local references to Java
objects</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Accessing
instance fields and static
fields</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Calling
instance methods and static
methods</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Performing
string and array
operations</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Generating
and handling Java
exceptions</FONT></UL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The number of JNI
functions is quite large and won&#8217;t be covered here. Instead, I&#8217;ll
show the rationale behind the use of these functions. For more detailed
information, consult your compiler&#8217;s JNI documentation.

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

<backtalk:display ID=TIJ3_APPENDIXB_I16>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you take a look at the <B>jni.h</B>
header file, you&#8217;ll see that inside the <B>#ifdef __cplusplus</B>
preprocessor conditional, the <B>JNIEnv_</B> structure is defined as a class
when compiled by a C++ compiler. This class contains a number of inline
functions that let you access the JNI functions with an easy and familiar
syntax. For example, the line of C++ code in the preceding
example:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>env-&gt;ReleaseStringUTFChars(jMsg, msg);</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">could also be called from C like this:

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

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

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>(*env)-&gt;ReleaseStringUTFChars(env, jMsg, msg);</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You&#8217;ll notice that the C style is
(naturally) more complicated&#8212;you need a double dereferencing of the
<B>env</B> pointer, and you must also pass the same pointer as the first
parameter to the JNI function call. The examples in this appendix use the C++
style.

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

<backtalk:display ID=TIJ3_APPENDIXB_I18>
</FONT><A NAME="_Toc481064953"></A><BR></P></DIV>
<A NAME="Heading634"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Accessing Java Strings</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">As an example of accessing a JNI
function, consider the code in <B>MsgImpl.cpp</B>. Here, the <B>JNIEnv</B>
argument <B>env</B> is used to access a Java <B>String</B>. Java <B>String</B>s
are in Unicode format, so if you receive one and want to pass it to a
non-Unicode function (<B>printf(&#160;)</B>, for example), you must first
convert it into ASCII characters with the JNI function
<B>GetStringUTFChars(&#160;)</B>. This function takes a Java <B>String</B> and
converts it to UTF-8 characters. (These are 8 bits wide to hold ASCII values or
16 bits wide to hold Unicode. If the content of the original string was composed
only of ASCII, the resulting string will be ASCII as well.)

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

<backtalk:display ID=TIJ3_APPENDIXB_I19>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>GetStringUTFChars(&#160;)</B> is one
of the member functions in <B>JNIEnv</B>. To access the JNI function, we use the
typical C++ syntax for calling a member function though a pointer. You use the
form above to access all of the JNI functions.

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

<backtalk:display ID=TIJ3_APPENDIXB_I20>
</FONT><A NAME="_Toc481064954"></A><BR></P></DIV>
<A NAME="Heading635"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Passing and using Java objects</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In the previous example we passed a
<B>String</B> to the native method. You can also pass Java objects of your own
creation to a native method. Inside your native method, you can access the
fields and methods of the object that was received.

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

<backtalk:display ID=TIJ3_APPENDIXB_I21>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To pass objects, use the ordinary Java
syntax when declaring the native method. In the example below,
<B>MyJavaClass</B> has one <B>public</B> field and one <B>public</B> method. The
class <B>UseObjects </B>declares a native method that takes an object of class
<B>MyJavaClass</B>. To see if the native method manipulates its argument, the
<B>public</B> field of the argument is set, the native method is called, and
then the value of the <B>public</B> field is printed.</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: appendixb:UseObjects.java</font>
<font color=#0000ff>class</font> MyJavaClass {
  <font color=#0000ff>public</font> <font color=#0000ff>int</font> aValue;
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> divByTwo() { aValue /= 2; }
}

<font color=#0000ff>public</font> <font color=#0000ff>class</font> UseObjects {
  <font color=#0000ff>private</font> <font color=#0000ff>native</font> <font color=#0000ff>void</font> 
    changeObject(MyJavaClass obj);
  <font color=#0000ff>static</font> {
    System.loadLibrary(<font color=#004488>"UseObjImpl"</font>);
    <font color=#009900>// Linux hack, if you can't get your library</font>
    <font color=#009900>// path set in your environment:</font>
    <font color=#009900>// System.load(</font>
    <font color=#009900>//"/home/bruce/tij2/appendixb/UseObjImpl.so");</font>
  }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    UseObjects app = <font color=#0000ff>new</font> UseObjects();
    MyJavaClass anObj = <font color=#0000ff>new</font> MyJavaClass();
    anObj.aValue = 2;

⌨️ 快捷键说明

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