📄 delphi-jni-3.html
字号:
<HTML>
<HEAD>
<meta name="keywords" content="Delphi, JNI, Java Native Interface, jni.pas, jni_md.pas, Borland, Inprise, Java, Invocation API">
<xxxlink rel="stylesheet" type="text/css" href="jni.css">
<style>
<!--
.Note1
{
margin-left: 0;
xfont-style: Italic;
background-color: rgb(255,255,240);
border-style: outset;
border-color: teal;
border-width: thin;
font-weight: normal;
vertical-align: top;
padding-top: 5px;
padding-bottom: 5px;
padding-left: 5px;
padding-right: 5px;
}
.SectionHeader
{
margin-left: 0;
font-size : 14pt;
font-weight : bold;
background-color: rgb(255,255,204);
border-style: solid;
border-color: black;
border-width: thin;
xvertical-align: top;
padding-top: 5px;
padding-bottom : 5px;
padding-left: 20px;
padding-right: 20px;
}
-->
</style>
<TITLE>Using the Java Native Interface with Delphi (Part Three - The Invocation API)</TITLE>
</HEAD>
<BODY BGCOLOR="#e0e0e0">
<a name="Top">
<H2><center>
Using the Java Native Interface with Delphi<br>
<font size=+1>(Part Three - The Invocation API)</font>
</center></H2>
<center><a href="mailto:jni@matthewmead.com">Matthew Mead</a></center>
<p>
<a href="http://www.pacifier.com/~mmead/jni/delphi/index.html">Home Page (on the Web) - News and Updates</a>
<p>
<a href="delphi-jni-1.html">Part One - Introduction and Tutorial</a>
<br>
<a href="delphi-jni-2.html">Part Two - Techniques and Examples</a>
<br>
Part Three - The Invocation API
<p>
<a href="http://www.delphi-jedi.org"><img src="gifs/btn_jedinow.gif" width="116" height="31"></a>
<h3><A NAME="Contents">Contents</A></h3>
<blockquote>
<table border=0 cellspacing=0 cellpadding=4>
<tr valign=top><td align=right colspan=1><A HREF="#Overview">Overview</A></td><td>What's the Invocation API?</td></tr>
<tr valign=top><td align=right colspan=1><A HREF="#Configuration">Configuration</A></td><td>Setting the proper path for the Invocation API.</td></tr>
<tr valign=top><td align=right colspan=1><A HREF="#Example">Example</A></td><td>Yet another <i>Hello World!</i> example.</td></tr>
<tr valign=top><td align=right colspan=1><A HREF="#CloserLook">A Closer Look</A></td><td>The <i>Hello World!</i> example in detail.</td></tr>
<tr valign=top><td align=right colspan=1><A HREF="#DifferentVersion">Alternate JRE Version</A></td><td>The <i>Hello World!</t> example using the JRE in the JDK 1.1.5.</td></tr>
<tr valign=top><td align=right colspan=1><A HREF="#DynamicLinking">Dynamic Loading</A></td><td>Choosing the JRE and version at runtime.</td></tr>
<tr valign=top><td align=right colspan=1><A HREF="#Example2">A GUI Example</A></td>
<td>This example shows a Delphi GUI application that uses a Java class to download web pages to your computer.</td></tr>
</table>
<blockquote>
<ol>
<li><a href="#Example2JavaCode">The Java Code</a> - A Java class called <tt>PageGrabber</tt> implements the functionality of downloading HTML pages.
<li><a href="#Example2DelphiCode">The Delphi Application</a> - A Delphi program called <tt>URLGrabber</tt> implements the UI for application.
<li><a href="#Example2Part1">Loading the VM</a> - Demonstrates loading the Java VM and storing the Java environment in a member of the Delphi class.
<li><a href="#Example2Part2">Class Method</a> - Demonstrates calling a Java class (static) method from the application's main thread.
<li><a href="#Example2Part3">Object Method</a> - Demonstrates calling a Java object (non-static) method from the application's main thread.
<li><a href="#Example2Part4">Threads</a> - Demonstrates calling a Java method from a worker thread.
<li><a href="#Example2Part5">Multiple Threads</a> - Demonstrates calling a Java method from multiple threads.
</ol>
<table border=0 cellspacing=0 cellpadding=4>
<tr valign=top><td align=right colspan=1><A HREF="#Summary">Summary</A></td><td>What's next?</td></tr>
</table>
</blockquote>
</blockquote>
<div class="SectionHeader">
<A NAME="Overview">Overview</A>
</div>
<BLOCKQUOTE>
This part of <i>Using the Java Native Interace with Delphi</i> is concerned with the Invocation API. This API is still part
of the JNI, but it is uses it in a somewhat different manner. Another term you may come across when dealing with the Invocation
API is the phrase <i>embedding the Java virtual machine</i> in an executable program or DLL. This makes the Invocation API
sound daunting, but, rest assurred, it's not as difficult as it may sound. Embedding in this context simply means
loading the DLL that contains the runtime code for the Java Virtual Machine. You'll see that it is no different than loading
any other DLL on your system.
<p>
Up to this point, our study of the Java Native Interface has focused
primarily on accessing Delphi (native) code from within Java code. There are many reasons why you would want to do this,
and one of the biggest reasons for doing this is to gain reuse of the millions of lines of proven, tested, efficient, and debugged Delphi code.
This is certainly much more productive than rewriting the Delphi code in Java. But what if you wanted to do it the other way around?
What if you had millions of lines of proven, tested, and debugged Java code that you would like to use in your Delphi application? Again,
it would be more productive to be able to reuse this code without having to rewrite it, this time, in Delphi. Well, that's one of the big features
of the Invocation API.
<p>
To contrast the Invocation API with the portion of the JNI we have been learning up until now, let's consider how each is invoked. In all of the
preceding tutorial and examples, the way the program was run was by typing:
<BLOCKQUOTE>
<pre>
java Main
</pre>
</BLOCKQUOTE>
at the command prompt. This caused the Java runtime (<tt><b>java.exe</b></tt>) to be executed. Since <tt><b>java.exe</b></tt> is an
executable program like any other, it is merely loaded into memory by the OS and begins executing. One of the things that the program does is to
locate and load the Java class <tt><b>Main.class</b></tt>. While loading this class, the Java runtime discovers that it also must load
a DLL (in our tutorial from <a href="delphi-jni-1.html">Part One</a>,
this is <tt><b>HelloWorldImpl.dll</b></tt>.) Recall this code from <tt><b>HelloWorld.java</b></tt>
<BLOCKQUOTE>
<pre>
System.loadLibrary("HelloWorldImpl");
</pre>
</BLOCKQUOTE>
This DLL is loaded and the interaction between the Delphi code and
the Java code takes place as described in <a href="delphi-jni-1.html">Part One</a> and <a href="delphi-jni-2.html">Part Two</a>
of these pages.
<p>
<b>Note: </b>
The important point to understand in this scenario is
that the Java runtime, <tt><b>java.exe</b></tt>, is what bootstrapped the whole process. The user thinks that she is running a Java
program and may or may not be aware that there is Delphi code executing in a DLL somewhere.
<p>
Now, with the Invocation API, things are slightly different. Instead of executing <tt><b>java.exe</b></tt> at the command prompt, we will
simply run a Delphi executable (let's just call it <tt><b>myprog.exe</b></tt> for now) that has the Java
runtime <i>embedded</i> in it. Again, embedding here simply means that we load the Java runtime from the executable,
instead of running it as a program typed at the command prompt. When we run <tt><b>myprog.exe</b></tt>, the OS loads the executable
into memory and it starts executing. One of the first things it does (or it could do it later) is to load the Java Virtual Machine. Since the
JVM is implemented in a DLL (<tt><b>jvm.dll</b></tt>), <tt><b>myprog.exe</b></tt> simply loads it as it would any other DLL it wished to link
with at runtime. Our program would execute code similar to this:
<BLOCKQUOTE>
<pre>
JVMHandle := LoadLibrary('jvm.dll');
</pre>
</BLOCKQUOTE>
Once this DLL is loaded into memory, <tt><b>myprog.exe</b></tt> can make calls into it just as it would with any other DLL and the interaction
between Delphi code and Java code takes place just as we've seen in all of our previous examples.
<p>
<b>Note: </b>
The important point to understand in this
scenario is that the Delphi program, <tt><b>myprog.exe</b></tt>, is what bootstrapped the whole process. The user thinks that she is running
a Delphi application and may or may not be aware that there is Java code executing in a Java VM somewhere.
<p>
Of course, the code shown above implies that the
Java VM, <tt><b>jvm.dll</b></tt>, is in the user's path somewhere. Also note that <tt><b>jvm.dll</b></tt> is the DLL that contains the
Java VM for version 1.2 of the JDK. The VM for version 1.1 is located in <tt><b>javai.dll</b></tt>. We will see how to detect and use both
versions later in this document.
<p>
<div class=Note1>
The Invocation API portion of the Java Native Interface translation is still a work in progress. Although the translation is complete, the
functionality of the wrapper class, <tt>TJavaVM</tt> is not. This doesn't mean that the wrapper class cannot be used, it simple means that it
is not complete. There are several more "features" that I'd like to add that hide the underlying API a little better. I felt that it
was more useful to release the translation in this state, rather than wait (what could be weeks or months or longer) until the other features
were completed. Maybe that
would be in a 1.1 (or 2.0) release of this translation. Also, as is the case with most software, until I receive and compile feedback, it's
difficult to decide what features are missing. So, if you think something is missing, it's because it probably is.
</div>
<p>
<a href="#Top">Back to top</a>
</BLOCKQUOTE>
<div class="SectionHeader">
<A NAME="Configuration">Configuring Your Machine (Windows platform)</A>
</div>
<BLOCKQUOTE>
As is the case with many of my Java experiences, setting up and configuring a compile-time and run-time environment seems to be
the hardest part of Java programming. You may not have had frustrating experiences, but I have. Setting up a Java Runtime Environment, JRE,
is not that difficult, though, once you know what to do. In fact, it's simply a matter of adding a couple of directories to your
PATH environment variable. If you don't have a JRE, you can download one from Sun's website. For this tutorial, you can
use the <a href="http://java.sun.com/products/jdk/1.2/jre/index.html">
JAVA 2 RUNTIME ENVIRONMENT Standard Edition</a>, which can be freely downloaded from Sun's website. If you installed the Java 2 SDK then you
probably already have a JRE installed.
<p>
<b>Java 2 JRE</b>
<p>
<blockquote>
If you are working with the Java 2 JRE,
there are 2 directories that need to be added to your PATH. The directories are <tt><b>\bin</b></tt> and <tt><b>\bin\classic</b></tt>, which
will be in the directory where you installed the JRE. For example, if you installed the JRE into the directory <tt><b>C:\JRE1.2</b></tt>, then
you would add
<pre>
C:\JRE1.2\bin;C:\JRE1.2\bin\classic
</pre>
to your PATH variable. The JRE (for Java 2) is implemented in the DLL named <tt>jvm.dll</tt>, which resides in <tt>\bin\classic</tt>. All of the
supporting JRE DLLs reside in directories relative to this directory, so it's important that you <b>DO NOT MOVE OR COPY THIS FILE</b> to
another location. If you do, you will encounter strange problems that will confuse you for hours (or days!)
</BLOCKQUOTE>
<p>
<b>JDK 1.1 JRE</b>
<p>
<blockquote>
If you are working with the JDK 1.1.x runtime then
there is only one directory that need to be added to your PATH. The directory is <tt><b>\bin</b></tt>, which
will be in the directory where you installed the JRE. For example, if you installed the JRE into the directory <tt><b>C:\JRE1.1.6</b></tt>, then
you would add
<pre>
C:\JRE1.1.6\bin
</pre>
to your PATH variable. The JRE (for JDK 1.1.x) is implemented in the DLL named <tt>javai.dll</tt>, which resides in <tt>\bin</tt>. All of the
supporting JRE DLLs reside in directories relative to this directory, so it's important that you <b>DO NOT MOVE OR COPY THIS FILE</b> to
another location. If you do, you will encounter strange problems that will confuse you for hours (or days!)
</BLOCKQUOTE>
<b>Notes</b>
<p>
During my testing of the Invocation API, I came across several "weird" situations. All of them were due to the fact that multiple versions
of <tt>jvm.dll</tt> and <tt>javai.dll</tt> were installed on my computer while I was devloping this code. Some of these DLLs failed to work
correctly or even at all. I don't know why. I also don't know where they came from. I have installed many, many programs on my computers and
certainly some of these programs felt is was necessary to install yet-another Java runtime on my machine. My advice to you is to make sure that
you have only one copy of <tt>jvm.dll</tt> and <tt>javai.dll</tt> in your PATH.
<p>
Also, because the names of the DLLs are different between JDK 1.1.x and Java 2, you can easily have both installed and accessible simultaneously.
This certainly makes it easy to test and use both versions of the JRE on the same machine (if you require this ability.)
<p>
<a href="#Top">Back to top</a>
</BLOCKQUOTE>
<div class="SectionHeader">
<A NAME="Example">A <i>Hello World!</i> Example</A>
</div>
<BLOCKQUOTE>
Yeah, I know what you're saying, <i>"No, not another Hello World! program..."</i> By using the same example in all cases, it will make
it easier for you to compare and contrast the different approaches. In the example from <a href="delphi-jni-1.html">Part One</a>, the words
<tt><b>Hello World!</b></tt> were printed to the screen by the Delphi DLL. The DLL was loaded by a Java program, which essentially
boot-strapped the whole process. Now, in this example, Java will print those words to the screen. The twist is that Java will be loaded by
a Delphi program. The Delphi program is boot-strapping the process this time as described in the <a href="#Overview">Overview</a> above.
<p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -