java system_深入分析java中的System
System是一個類,這個System類主要是一些與系統相關的屬性和方法的集合,而且其內部的方法全部是靜態的,所以我們直接使用System直接調用就好,比如我們常用的一個System.out.print。這篇文章我們就來分析一下System類。
一、System概述
System就是系統的意思。因此它的主要操作肯定也是和系統信息有關。這個類位于java.lang包??赡芪覀兌加幸粋€疑惑,我們從來沒見過System被實例化,這是因為System類內部的構造函數是私有的,在外部不能訪問,因此也就不能被實例化了。
他主要有如下功能:
(1)系統信息的訪問,如外部屬性和環境變量等
(2)垃圾回收相關操作
(3)標準輸入輸出
(4)比較常用的其他操作,比如數組拷貝
接下來我們就對這些功能進行一個測試與描述:
二、System功能演示
1、獲取設置屬性方法
也就是說我們的System如何獲取系統的屬性,或者說是調用哪個方法獲取屬性。
(1)contains(Object value)、containsKey(Object key):判斷給定的參數或屬性關鍵字在屬性表中有定義,返回True或者False;
(2)getProperty(String key)、getProperty(String key, String default):根據參數獲取屬性
(3)list(PrintStream s)、list(PrintWriter w): 在輸出流中輸出屬性表內容;
(4)size():返回當前屬性表中定義的屬性關鍵字個數。
我們當然可以設置屬性:
(1)put(Object key, Object value) :向屬性表中追加屬性關鍵字和關鍵字的值;
(2)remove(Object key) :從屬性表中刪除關鍵字。
2、獲取系統屬性
上面我們可以直接使用System.contains等方法來調用,下面我們可以輸入以下參數來獲取系統信息。
功能
描述java.version
Java 運行時環境版本
java.vendor
Java 運行時環境供應商
java.vendor.url
Java 供應商的 URL
java.home
Java 安裝目錄
java.vm.specification.version
Java 虛擬機規范版本
java.vm.specification.vendor
Java 虛擬機規范供應商
java.vm.specification.name
Java 虛擬機規范名稱
java.vm.version
Java 虛擬機實現版本
java.vm.vendor
Java 虛擬機實現供應商
java.vm.name
Java 虛擬機實現名稱
java.specification.version
Java 運行時環境規范版本
java.specification.vendor
Java 運行時環境規范供應商
java.specification.name
Java 運行時環境規范名稱
java.class.version
Java 類格式版本號
java.class.path
Java 類路徑
java.library.path
加載庫時搜索的路徑列表
java.io.tmpdir
默認的臨時文件路徑
java.compiler
要使用的 JIT 編譯器的名稱
java.ext.dirs
一個或多個擴展目錄的路徑
os.name
操作系統的名稱
os.arch
操作系統的架構
os.version
操作系統的版本
file.separator
文件分隔符(在 UNIX 系統中是“/”)
path.separator
路徑分隔符(在 UNIX 系統中是“:”)
line.separator
行分隔符(在 UNIX 系統中是“/n”)
user.name
用戶的賬戶名稱
user.home
用戶的主目錄
user.dir
用戶的當前工作目錄
然后使用代碼測試一下幾個比較典型的吧:
public class SystemTest {
public static void main(String[] args) {
System.out.println("Java 運行時環境版本 :" + System.getProperty("java.version"));
System.out.println("Java 運行時環境供應商 :" + System.getProperty("java.vendor"));
System.out.println("Java 運行時環境規范版本 :" + System.getProperty("java.specification.version"));
System.out.println("Java 運行時環境規范供應商:" + System.getProperty("java.specification.vendor"));
System.out.println("Java 運行時環境規范名稱 :" + System.getProperty("java.specification.name"));
System.out.println("操作系統的名稱:" + System.getProperty("os.name"));
System.out.println("操作系統的架構:" + System.getProperty("os.arch"));
System.out.println("操作系統的版本:" + System.getProperty("os.version"));
System.out.println("用戶的賬戶名稱 :" + System.getProperty("user.name"));
System.out.println("用戶的主目錄 :" + System.getProperty("user.home"));
System.out.println("用戶的當前工作目錄 : " + System.getProperty("user.dir"));
}
}
當然運行一下我們的控制臺就有結果了:
在這里只是挑選了一部分進行測試,參數已經列出來了,其他的可以自己測。
三、常見操作
1、拷貝數組arraycopy
public class SystemTest {
public static void main(String[] args) {
int[] arr1 = {1,2,3,4,5 };
int[] arr2 = { 6,7,8,9,10};
/*
* 第一個參數arr1:被復制的數組
* 第二個參數1:arr1中要復制的起始位置
* 第三個參數arr2:目標數組
* 第四個參數0:目標數組的復制起始位置
* 第五個參數3:目標數組的復制結束位置
*/
System.arraycopy(arr1, 1, arr2, 0, 3);
for (int i = 0; i < 5; i++)
System.out.print(arr2[i] + " ");
}
}
2、獲取系統時間
public class SystemTest {
public static void main(String[] args) {
System.out.println(System.currentTimeMillis());
System.out.println(System.nanoTime());
}
}
//輸出:1565841056267(時間戳)
//輸出:1130607059454400
四、垃圾回收相關操作:System.gc
這句話表明運行了垃圾回收器。java虛擬機會回收一下系統垃圾,比如說沒有使用的對象。
public class SystemTest {
public static void main(String[] args) {
User user = new User();//新建一個對象
System.out.println(user.toString());
user=null;//將引用置為空
System.gc();//垃圾回收
System.out.println(user.toString());
}
}
我們看一下運行結果再來分析
我們可以看到,在進行完垃圾回收之后,再輸入User相關信息時由于找不到對象,因此報了空指針異常。
我們進入到System.gc內部看一下,看看內部執行了什么操作,
public static void gc() {
Runtime.getRuntime().gc();
}
在這里我們可以看到其實是執行了Runtime的垃圾回收操作。我們在進入會發現其實垃圾回收就是Runtime做的。
五、源碼分析
1、初始化
我們進入到System的源碼中,可以看到首先由這樣的描述:
/* register the natives via the static initializer.
* VM will invoke the initializeSystemClass method to complete
* the initialization for this class separated from clinit.
* Note that to use properties set by the VM, see the constraints
* described in the initializeSystemClass method.
*/
private static native void registerNatives();
static {
registerNatives();
}
/** Don't let anyone instantiate this class */
private System() {}
上面是什么意思呢?
首先:registerNatives()方法是一個入口方法,注冊成了natives,也就是說該方法會令vm通過調用initializeSystemClass方法來完成初始化工作。
然后:構造函數被設置成private,說明我們不能實例化這個類,注釋也已經說明了。
既然System初始化的操作是通過initializeSystemClass,我們不如進入到這個類中去看看。
private static void initializeSystemClass() {
//第一步:初始化props
props = new Properties();
initProperties(props); // initialized by the VM
//第二步:vm保存刪除一些系統屬性
sun.misc.VM.saveAndRemoveProperties(props);
//第三步:獲取系統分隔符
lineSeparator = props.getProperty("line.separator");
//第四步:初始化系統的一些配置
sun.misc.Version.init();
//第五步:輸入輸出流初始化
FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
setIn0(new BufferedInputStream(fdIn));
setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding")));
setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding")));
loadLibrary("zip");
//第六步:設置平臺相關的信號處理
Terminator.setup();
//第七步:初始化系統環境
sun.misc.VM.initializeOSEnvironment();
//第八步:把自己添加到線程組
Thread current = Thread.currentThread();
current.getThreadGroup().add(current);
//第九步:初始化
setJavaLangAccess();
sun.misc.VM.booted();
}
通過initializeSystemClass,我們已經能夠明白System是如何初始化的,對于每一步,我們可以繼續深入下去觀察其具體實現,在這里就不贅述了。
2、類屬性
類屬性其實主要是輸入輸出流
public final static InputStream in = null;
public final static PrintStream out = null;
public final static PrintStream err = null;
3、類方法
在這里肯定不能所有的方法都講一遍,在這里列舉幾個比較重要的方法。
(1)getProperty:獲取系統屬性
public static String getProperty(String key) {
//校驗key的值
checkKey(key);
//檢查參數是否安全
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertyAccess(key);
}
//獲取系統屬性
return props.getProperty(key);
}
我們在這里發現,其實獲取屬性的操作最關鍵的就是最后一句props.getProperty(key)。我們進入到這個方法看看:
public String getProperty(String key) {
Object oval = super.get(key);
String sval = (oval instanceof String) ? (String)oval : null;
return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
}
也就是說其實是 一直是回調defaults.getProperty(key),讓父類一直不停的去調用。最后返回一個String。
(2)checkKey:校驗key
private static void checkKey(String key) {
if (key == null) {
throw new NullPointerException("key can't be null");
}
if (key.equals("")) {
throw new IllegalArgumentException("key can't be empty");
}
}
里面很簡單就是看看是否為空。
(3)setProperties:設置系統屬性
public static void setProperties(Properties props) {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertiesAccess();
}
if (props == null) {
props = new Properties();
initProperties(props);
}
System.props = props;
}
最核心的就是最后一行,但是前面首先檢驗了是否是系統安全的屬性,而且也根據這個屬性初始化了一次。我們進入initProperties。
private static native Properties initProperties(Properties props);
這是一個native方法。
(4)exit():退出當前的jvm
public static void exit(int status) {
Runtime.getRuntime().exit(status);
}
其實調用的也是runtime的退出方法。
(5)其他方法
public static native long currentTimeMillis();
public static native long nanoTime();
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
public static native int identityHashCode(Object x);
我們會發現經常操作的這些方法其實也是native的。
(6)安全管理機制
與之相關的方法有三個
public static void setSecurityManager(final SecurityManager s) {
try {
s.checkPackageAccess("java.lang");
} catch (Exception e) {
}
setSecurityManager0(s);
}
第二個:
private static synchronized void setSecurityManager0(final SecurityManager s) {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission ("setSecurityManager"));
}
if ((s != null) && (s.getClass().getClassLoader() != null)) {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
s.getClass().getProtectionDomain().implies(SecurityConstants.ALL_PERMISSION);
return null;
}
});
}
security = s;
InetAddressCachePolicy.setIfNotSet(InetAddressCachePolicy.FOREVER);
}
還有最后一個
public static SecurityManager getSecurityManager() {
return security;
}
OK。源碼分析也就先說到這里,對于System類要知道其基本的內部實現以及常用的操作即可。
總結
以上是生活随笔為你收集整理的java system_深入分析java中的System的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: navicat怎么查看数据库的url_连
- 下一篇: 常用并发工具类(锁和线程间通信工具类)