System 类实现了许多系统实用程序,其中一些已在上一节配置实用程序中介绍过,本节介绍一些其他系统实用程序。
系统提供了几个预定义的I/O对象,这些对象在Java应用程序中非常有用,可以从命令行启动,它们实现了大多数操作系统提供的标准I/O流,以及用于输入密码的控制台对象,有关更多信息,请参阅基础I/O课程中的命令行I/O。
在属性中,我们研究了应用程序可以使用 Properties
对象来维护其配置的方式,Java平台本身使用 Properties
对象来维护自己的配置, System
类维护一个 Properties
对象,该对象描述当前工作环境的配置,系统属性包括有关当前用户、Java运行时的当前版本以及用于分隔文件路径名的组件的字符的信息。
下表描述了一些最重要的系统属性。
键 | 含义 |
---|---|
"file.separator" | 用于分隔文件路径组件的字符,这在UNIX上是“/”,在Windows上是“/” |
"java.class.path" |
用于查找包含类文件的目录和JAR存档的路径,类路径的元素由 path.separator
属性中指定的特定于平台的字符分隔 |
"java.home" | Java Runtime Environment(JRE)的安装目录 |
"java.vendor" | JRE vendor名称 |
"java.vendor.url" | JRE vendor URL |
"java.version" | JRE版本号 |
"line.separator" | 操作系统用于分隔文本文件中的行的序列 |
"os.arch" | 操作系统架构 |
"os.name" | 操作系统名称 |
"path.separator" |
java.class.path
中使用的路径分隔符 |
"user.dir" | 用户工作目录 |
"user.home" | 用户主目录 |
"user.name" | 用户帐户名称 |
安全考虑:安全管理器可以限制对系统属性的访问,这通常是applet中的一个问题,它无法读取某些系统属性,也无法写入任何系统属性,有关访问applet中的系统属性的更多信息,请参阅“使用Java Rich Internet Applications进行更多操作”课程中的“系统属性”。
System
类有两个用于读取系统属性的方法: getProperty
和 getProperties
。
System
类有两个不同版本的 getProperty
,两者都检索参数列表中指定的属性的值,两个 getProperty
方法中较简单的方法是使用单个参数,即属性键。例如,要获取 path.separator
的值,请使用以下语句:
System.getProperty("path.separator");
getProperty
方法返回包含属性值的字符串,如果该属性不存在,则此版本的 getProperty
返回 null
。
另一个版本的 getProperty
需要两个 String
参数:第一个参数是查找的键,如果无法找到键或没有值,则第二个参数是要返回的默认值。例如,以下对 getProperty
的调用会查找名为 subliminal.message
的 System
属性,这不是有效的系统属性,因此该方法不是返回 null
,而是返回作为第二个参数提供的默认值:"Buy StayPuft Marshmallows!"。
System.getProperty("subliminal.message", "Buy StayPuft Marshmallows!");
System
类提供的访问属性值的最后一个方法是 getProperties
方法,该方法返回一个 Properties
对象,该对象包含一组完整的系统属性定义。
要修改现有的系统属性集,请使用 System.setProperties
,此方法采用已初始化为包含要设置的属性的 Properties
对象,此方法使用 Properties
对象表示的新集替换整个系统属性集。
更改系统属性可能存在危险,应谨慎处理,许多系统属性在启动后不会重新读取,而是用于提供信息,更改某些属性可能会产生意外的副作用。
下一个示例 PropertiesTest
创建一个 Properties
对象,并从 myProperties.txt
初始化它。
subliminal.message=Buy StayPuft Marshmallows!
然后, PropertiesTest
使用 System.setProperties
将新的 Properties
对象安装为当前的系统属性集。
import java.io.FileInputStream; import java.util.Properties; public class PropertiesTest { public static void main(String[] args) throws Exception { // set up new properties object // from file "myProperties.txt" FileInputStream propFile = new FileInputStream( "myProperties.txt"); Properties p = new Properties(System.getProperties()); p.load(propFile); // set the system properties System.setProperties(p); // display new properties System.getProperties().list(System.out); } }
注意 PropertiesTest
如何创建 Properties
对象 p
,它被用作 setProperties
的参数:
Properties p = new Properties(System.getProperties());
此语句使用当前系统属性集初始化新属性对象 p
,在此小应用程序的情况下,该属性是由运行时系统初始化的属性集。然后,应用程序从文件 myProperties.txt
将其他属性加载到 p
中,并将系统属性设置为 p
。这具有将 myProperties.txt
中列出的属性添加到运行时系统在启动时创建的属性集的效果,请注意,应用程序可以创建没有任何默认 Properties
对象的 p
,如下所示:
Properties p = new Properties();
另请注意,系统属性的值可以被覆盖!例如,如果 myProperties.txt
包含以下行,则将覆盖 java.vendor
系统属性:
java.vendor=Acme Software Company
通常,请注意不要覆盖系统属性。
setProperties
方法更改当前正在运行的应用程序的系统属性集,这些变化并不持久。也就是说,更改应用程序中的系统属性不会影响将来对此解释程序或任何其他应用程序的Java解释程序的调用,运行时系统每次启动时都会重新初始化系统属性,如果要保持对系统属性的更改,则应用程序必须在退出之前将值写入某个文件,并在启动时再次读取它们。
安全管理器是定义应用程序安全策略的对象,此策略指定不安全或敏感的操作,安全策略不允许的任何操作都会导致抛出 SecurityException ,应用程序还可以查询其安全管理器以发现允许的操作。
通常,Web applet与浏览器或Java Web Start插件提供的安全管理器一起运行,其他类型的应用程序通常在没有安全管理器的情况下运行,除非应用程序本身定义了安全管理器。如果没有安全管理器,则该应用程序没有安全策略,并且没有任何限制。
本节介绍应用程序如何与现有安全管理器进行交互,有关更多详细信息,包括有关如何设计安全管理器的信息,请参阅 安全指南 。
安全管理器是 SecurityManager
类型的对象,要获取对此对象的引用,请调用 System.getSecurityManager
。
SecurityManager appsm = System.getSecurityManager();
如果没有安全管理器,则此方法返回 null
。
一旦应用程序具有对安全管理器对象的引用,它就可以请求执行特定事务的权限,标准库中的许多类都是这样做的。例如,以退出状态终止Java虚拟机的 System.exit
调用 SecurityManager.checkExit
以确保当前线程具有关闭应用程序的权限。
SecurityManager
类定义了许多用于验证其他类型操作的其他方法。例如, SecurityManager.checkAccess
验证线程访问, SecurityManager.checkPropertyAccess
验证对指定属性的访问,每个操作或一组操作都有自己的 checkXXX()
方法。
此外, checkXXX()
方法集表示已受安全管理器保护的操作集,通常,应用程序不必直接调用任何 checkXXX()
方法。
在没有安全管理器的情况下,许多常规操作在使用安全管理器运行时都会抛出 SecurityException
,即使在调用未记录为抛出 SecurityException
的方法时也是如此,例如,请考虑以下用于读取文件的代码:
reader = new FileReader("xanadu.txt");
在缺少安全管理器的情况下,如果 xanadu.txt
存在且可读,则此语句无错误地执行,但是假设此语句插入到Web applet中,该applet通常在不允许文件输入的安全管理器下运行,可能会导致以下错误消息:
appletviewer fileApplet.html Exception in thread "AWT-EventQueue-1" java.security.AccessControlException: access denied (java.io.FilePermission characteroutput.txt write) at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323) at java.security.AccessController.checkPermission(AccessController.java:546) at java.lang.SecurityManager.checkPermission(SecurityManager.java:532) at java.lang.SecurityManager.checkWrite(SecurityManager.java:962) at java.io.FileOutputStream.<init>(FileOutputStream.java:169) at java.io.FileOutputStream.<init>(FileOutputStream.java:70) at java.io.FileWriter.<init>(FileWriter.java:46) ...
请注意,在这种情况下抛出的特定异常 java.security.AccessControlException
是 SecurityException
的子类。
本节介绍了前面几节中未介绍的 System
中的一些方法。
arrayCopy
方法有效地在数组之间复制数据,有关更多信息,请参阅语言基础知识课程中的数组。
currentTimeMillis
和 nanoTime
方法可用于测量应用程序执行期间的时间间隔。要以毫秒为单位测量时间间隔,请在间隔的开始和结束时调用 currentTimeMillis
两次,并从第二个返回值中减去第一个值。同样,调用 nanoTime
两次测量一个纳秒的间隔。
currentTimeMillis
和 nanoTime
的准确性受操作系统提供的时间服务的限制,不要假设 currentTimeMillis
精确到最接近的毫秒,或者 nanoTime
精确到最接近的纳秒。此外, currentTimeMillis
和 nanoTime
都不应用于确定当前时间,使用高级方法,例如 java.util.Calendar.getInstance
。
exit 方法使Java虚拟机关闭,并使用参数指定的整数退出状态,退出状态可用于启动应用程序的进程,按照惯例,退出状态为0表示应用程序正常终止,而任何其他值都是错误代码。、
上一篇:配置实用工具