System類實現了許多系統實用程序,其中一些已在上一節配置實用程序中介紹過,本節介紹一些其餘系統實用程序。html
系統提供了幾個預約義的I/O對象,這些對象在Java應用程序中很是有用,能夠從命令行啓動,它們實現了大多數操做系統提供的標準I/O流,以及用於輸入密碼的控制檯對象,有關更多信息,請參閱基礎I/O課程中的命令行I/O。java
在屬性中,咱們研究了應用程序可使用Properties
對象來維護其配置的方式,Java平臺自己使用Properties
對象來維護本身的配置,System
類維護一個Properties
對象,該對象描述當前工做環境的配置,系統屬性包括有關當前用戶、Java運行時的當前版本以及用於分隔文件路徑名的組件的字符的信息。git
下表描述了一些最重要的系統屬性。github
鍵 | 含義 |
---|---|
"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
。segmentfault
System
類有兩個不一樣版本的getProperty
,二者都檢索參數列表中指定的屬性的值,兩個getProperty
方法中較簡單的方法是使用單個參數,即屬性鍵。例如,要獲取path.separator
的值,請使用如下語句:api
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表示應用程序正常終止,而任何其餘值都是錯誤代碼。、