Java教程是为JDK 8编写的。本页中描述的示例和实践不利用后续版本中引入的改进,并且可能使用已不再可用的技术。
有关Java SE 9及其后续版本中更新的语言功能的概述,请参阅Java语言更改。
有关所有JDK版本的新功能、增强功能以及已删除或已弃用选项的信息,请参阅JDK发布说明。
服务器和客户端程序运行时都安装了安全管理器。当您运行任何一个程序时,都需要指定一个安全策略文件,以便为代码授予所需的安全权限。以下是一个用于服务器程序的示例策略文件:
grant codeBase "file:/home/ann/src/" { permission java.security.AllPermission; };
以下是一个用于客户端程序的示例策略文件:
grant codeBase "file:/home/jones/src/" { permission java.security.AllPermission; };
对于这两个示例策略文件,所有权限都授予了程序本地类路径中的类,因为本地应用程序代码是可信任的,但没有为从其他位置下载的代码授予任何权限。因此,计算引擎服务器限制了执行任何需要安全权限的操作的任务(其代码未知是否可信任且可能是恶意的)。示例客户端的Pi
任务不需要执行任何权限。
在这个示例中,服务器程序的策略文件名为server.policy
,客户端程序的策略文件名为client.policy
。
在启动计算引擎之前,您需要先启动RMI注册表。RMI注册表是一个简单的服务器端引导命名工具,用于使远程客户端获取到初始远程对象的引用。可以使用rmiregistry
命令来启动RMI注册表。在执行rmiregistry
之前,必须确保您将在其中运行rmiregistry
的shell或窗口要么没有设置CLASSPATH
环境变量,要么CLASSPATH
环境变量中不包含您希望下载到远程对象的客户端的任何类的路径。
要在服务器上启动注册表,请执行rmiregistry
命令。该命令不会产生任何输出,通常在后台运行。对于此示例,注册表在主机mycomputer
上启动。
Microsoft Windows(如果没有start
命令,则使用javaw
):
start rmiregistry
Solaris OS或Linux:
rmiregistry &
默认情况下,注册表在端口1099上运行。要在不同的端口上启动注册表,请在命令行中指定端口号。不要忘记取消设置CLASSPATH
环境变量。
Microsoft Windows:
start rmiregistry 2001
Solaris OS或Linux:
rmiregistry 2001 &
注册表启动后,您可以启动服务器。您需要确保compute.jar
文件和远程对象实现类都在类路径中。启动计算引擎时,您需要使用java.rmi.server.codebase
属性指定服务器的类在网络中可访问的位置。在这个示例中,要下载的服务器端类是Compute
和Task
接口,它们位于用户ann
的public_html\classes
目录下的compute.jar
文件中。计算引擎服务器在与注册表启动的主机mycomputer
上启动。
Microsoft Windows:
java -cp c:\home\ann\src;c:\home\ann\public_html\classes\compute.jar -Djava.rmi.server.codebase=file:/c:/home/ann/public_html/classes/compute.jar -Djava.rmi.server.hostname=mycomputer.example.com -Djava.security.policy=server.policy engine.ComputeEngine
Solaris OS or Linux:
java -cp /home/ann/src:/home/ann/public_html/classes/compute.jar -Djava.rmi.server.codebase=http://mycomputer/~ann/classes/compute.jar -Djava.rmi.server.hostname=mycomputer.example.com -Djava.security.policy=server.policy engine.ComputeEngine
上述java
命令定义了以下系统属性:
java.rmi.server.codebase
属性指定从此服务器生成的类的定义可以下载的位置,即代码库URL。如果代码库指定了目录层次结构(而不是JAR文件),必须在代码库URL的末尾包含一个斜杠。java.rmi.server.hostname
属性指定要放在该Java虚拟机中导出的远程对象存根中的主机名或地址。当客户端尝试通信远程方法调用时,该值是客户端使用的主机名或地址。默认情况下,RMI实现使用由java.net.InetAddress.getLocalHost
API指示的服务器IP地址。然而,有时这个地址对于所有客户端都不合适,一个完全限定的主机名会更有效。为确保RMI使用可从所有潜在客户端路由到的服务器的主机名(或IP地址),请设置java.rmi.server.hostname
属性。java.security.policy
属性用于指定包含您打算授予的权限的策略文件。注册表和计算引擎运行后,您可以启动客户端,指定以下内容:
Pi
类)的位置,使用java.rmi.server.codebase
属性java.security.policy
属性,用于指定包含您打算授予各种代码的权限的安全策略文件Compute
远程对象)和在计算中使用的小数位数在另一台主机上启动客户端(例如,名为mysecondcomputer
的主机):
Microsoft Windows:
java -cp c:\home\jones\src;c:\home\jones\public_html\classes\compute.jar -Djava.rmi.server.codebase=file:/c:/home/jones/public_html/classes/ -Djava.security.policy=client.policy client.ComputePi mycomputer.example.com 45
Solaris OS或Linux:
java -cp /home/jones/src:/home/jones/public_html/classes/compute.jar -Djava.rmi.server.codebase=http://mysecondcomputer/~jones/classes/ -Djava.security.policy=client.policy client.ComputePi mycomputer.example.com 45
请注意,通过命令行设置类路径,以便解释器能够找到客户端类和包含接口的JAR文件。还请注意,java.rmi.server.codebase
属性的值指定了一个目录层次结构,并以斜杠结尾。
启动客户端后,将显示以下输出:
3.141592653589793238462643383279502884197169399
下图说明了rmiregistry
、ComputeEngine
服务器和ComputePi
客户端在程序执行过程中获取类的位置。
当ComputeEngine
服务器在注册表中绑定其远程对象引用时,注册表会从服务器的Web服务器或文件系统下载存根类所依赖的Compute
和Task
接口。这些类的下载取决于启动服务器时使用的代码库URL的类型。
由于ComputePi
客户端在其类路径中都有Compute
和Task
接口,因此它会从其类路径中加载它们的定义,而不是从服务器的代码库中加载。
最后,当Pi
对象通过executeTask
远程调用传递给ComputeEngine
对象时,Pi
类将被加载到ComputeEngine
服务器的Java虚拟机中。该类由服务器从客户端的Web服务器或文件系统加载,取决于启动客户端时使用的代码库URL的类型。