System类
不能被实例化
提供了标准输入、标准输出和错误输出流
可以访问外部定义的属性和环境变量
提供加载文件和库的方式
包含一个用于快速复制数组部分元素的工具方法
构造方法私有化
/** Don't let anyone instantiate this class */
private 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();
}
本地方法,通过 关键字 native 来声明,JDK不实现,JVM实现。可以理解为,接口 和 接口的实现类的关系,JDK中声明的native方法 是接口,JVM对native方法的实现 是 接口的实现。
/* Only register the performance-critical methods */
static JNINativeMethod methods[] = {
{"currentTimeMillis", "()J", (void *)&JVM_CurrentTimeMillis},
{"nanoTime", "()J", (void *)&JVM_NanoTime},
{"arraycopy", "(" OBJ "I" OBJ "II)V", (void *)&JVM_ArrayCopy},
};
#undef OBJ
JNIEXPORT void JNICALL
Java_java_lang_System_registerNatives(JNIEnv *env, jclass cls)
{
(*env)->RegisterNatives(env, cls,
methods, sizeof(methods)/sizeof(methods[0]));
}
初始化System类
/**
* Initialize the system class. Called after thread initialization.
*/
private static void initializeSystemClass() {}
initializeSystemClass
方法用于初始化 Java 系统类,确保在主线程初始化后系统资源和环境配置正确。主要步骤如下:
- 初始化系统属性:创建并初始化
Properties
对象,保存系统属性,native方法 - 处理内部属性:移除某些仅供内部使用的系统属性。
- 设置系统行分割符:line.separator
- 设置版本属性
- 设置输入输出流:初始化标准输入、输出和错误流。
- 加载库和信号处理:加载必要的本地库(如 zip 库),设置 Java 信号处理器。
- 初始化操作系统环境:根据需要调整操作系统的配置。
- 添加主线程到线程组:将主线程手动添加到其线程组。
- 注册共享秘密:设置
JavaLangAccess
接口以访问内部实现。 - 标记 JVM 启动完成:通知 JVM 初始化已完成
系统分割符:
file.separator:文件路径分隔符(如 Windows 的 \ 或 Unix/Linux/macOS 的 /)
path.separator:路径列表分隔符(如 Windows 的 ; 或 Unix/Linux/macOS 的 :)
line.separator:行分隔符(如 Windows 的 \r\n 或 Unix/Linux/macOS 的 \n
设置版本属性:
System.setProperty("java.version", "1.8.0_431");
System.setProperty("java.runtime.version", "1.8.0_431-b10");
System.setProperty("java.runtime.name", "Java(TM) SE Runtime Environment");
数组copy
数组,是一个定长的对象。如果需要存储的数据长度 超过 初始定义的长度时,就需要 扩容。将原数组中的数据 copy 到另一个新的数组中。
必须使用 System类提供的 arrayCopy 来完成 数组的copy。
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
系统时间
public static native long currentTimeMillis();
public static native long nanoTime();
获取环境变量
环境变量是当前系统的,只能读取现有的环境变量的数据
public static java.util.Map<String,String> getenv() {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("getenv.*"));
}
return ProcessEnvironment.getenv();
}
public static String getenv(String name) {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("getenv."+name));
}
return ProcessEnvironment.getenv(name);
}
操作属性变量
对于属性的操作,是System类中 持有 java.util.Properties,也是一种map结构。
设置属性
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;
}
public static String setProperty(String key, String value) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new PropertyPermission(key,
SecurityConstants.PROPERTY_WRITE_ACTION));
}
return (String) props.setProperty(key, value);
}
读取属性
public static Properties getProperties() {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertiesAccess();
}
return props;
}
public static String getProperty(String key) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertyAccess(key);
}
return props.getProperty(key);
}
public static String getProperty(String key, String def) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertyAccess(key);
}
return props.getProperty(key, def);
}
删除指定属性
public static String clearProperty(String key) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new PropertyPermission(key, "write"));
}
return (String) props.remove(key);
}
4个特殊的方法
都是调用Runtime的方法
public static void exit(int status) {
Runtime.getRuntime().exit(status);
}
public static void gc() {
Runtime.getRuntime().gc();
}
@CallerSensitive
public static void load(String filename) {
Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);
}
@CallerSensitive
public static void loadLibrary(String libname) {
Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
}