在研究一些源碼的時候,會發現,源碼中有時會通過VM.getSavedProperty
獲取一些參數,我們平時寫應用時,獲取系統參數的時候,通常是使用System.getProperty
,那VM.getSavedProperty
和System.getProperty
區別是什麼呢?
在System
的initializeSystemClass
方法中,會初始化系統參數,初始化系統參數的時候:
1、首先獲取所有的系統參數放在System
中
2、有一些可由VM選項控制的系統配置,例如直接內存的最大數量和用於支持自動裝箱的對象標識語義的整數緩存大小。 通常,該庫將從VM設置的屬性中獲取這些值。 如果這些屬性僅用於內部實現,則應從系統屬性中刪除這些屬性。
private static void initializeSystemClass() {
// VM might invoke JNU_NewStringPlatform() to set those encoding
// sensitive properties (user.home, user.name, boot.class.path, etc.)
// during "props" initialization, in which it may need access, via
// System.getProperty(), to the related system encoding property that
// have been initialized (put into "props") at early stage of the
// initialization. So make sure the "props" is available at the
// very beginning of the initialization and all system properties to
// be put into it directly.
props = new Properties();
//初始化系統參數
initProperties(props); // initialized by the VM
// There are certain system configurations that may be controlled by
// VM options such as the maximum amount of direct memory and
// Integer cache size used to support the object identity semantics
// of autoboxing. Typically, the library will obtain these values
// from the properties set by the VM. If the properties are for
// internal implementation use only, these properties should be
// removed from the system properties.
//
// See java.lang.Integer.IntegerCache and the
// sun.misc.VM.saveAndRemoveProperties method for example.
//
// Save a private copy of the system properties object that
// can only be accessed by the internal implementation. Remove
// certain system properties that are not intended for public access.
//有一些可由VM選項控制的系統配置,例如直接內存的最大數量和用於支持自動裝箱的對象標識語義的整數緩存大小。
//通常,該庫將從VM設置的屬性中獲取這些值。 如果這些屬性僅用於內部實現,則應從系統屬性中刪除這些屬性。
sun.misc.VM.saveAndRemoveProperties(props);
//......
}
具體的保存並且刪除的代碼如下:
public static void saveAndRemoveProperties(Properties var0) {
if (booted) {
throw new IllegalStateException("System initialization has completed");
} else {
savedProps.putAll(var0);
String var1 = (String)var0.remove("sun.nio.MaxDirectMemorySize");
if (var1 != null) {
if (var1.equals("-1")) {
directMemory = Runtime.getRuntime().maxMemory();
} else {
long var2 = Long.parseLong(var1);
if (var2 > -1L) {
directMemory = var2;
}
}
}
var1 = (String)var0.remove("sun.nio.PageAlignDirectMemory");
if ("true".equals(var1)) {
pageAlignDirectMemory = true;
}
var1 = var0.getProperty("sun.lang.ClassLoader.allowArraySyntax");
allowArraySyntax = var1 == null ? defaultAllowArraySyntax : Boolean.parseBoolean(var1);
var0.remove("java.lang.Integer.IntegerCache.high");
var0.remove("sun.zip.disableMemoryMapping");
var0.remove("sun.java.launcher.diag");
var0.remove("sun.cds.enableSharedLookupCache");
}
}
看到這兒,就明白了,VM中保存的是全量的參數,System
中去除了一些僅用於內部實現的屬性。
可以用java.lang.Integer.IntegerCache.high
驗證一下,啓動參數配置如下:
-Djava.lang.Integer.IntegerCache.high=256 -Dtest=128
執行如下代碼:
public static void main(String[] args) {
String vmh = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
String vmt = sun.misc.VM.getSavedProperty("test");
String smh = System.getProperty("java.lang.Integer.IntegerCache.high");
String smt = System.getProperty("test");
System.err.println(vmh);
System.err.println(vmh);
System.err.println(smh);
System.err.println(smt);
}
執行結果:
256
256
null
128