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相关推荐

  1. 【java】深入分析Java反射-动态代理 proxy

    1.概述 转载:深入分析Java反射(四)-动态代理 [Java]Java 反射机制浅析 [Java]java代理 静态代理 动态代理 proxy [java]静态代理 proxy 2.动态代理的简介 ...

  2. java中特殊流程控制语句,深入分析JAVA流程控制语句

    复合语句 Java的复合语句是以整个区块为单位的语句,由{}以及{}内包含的内容组成 对于复合语句来说,复合语句创建了一个局部变量的作用域,该作用域中变量可以创建并使用,在作用域外使用则会报错,找不到 ...

  3. java final 实例_Java中final实现原理的深入分析(附示例)

    本篇文章给大家带来的内容是关于Java中final实现原理的深入分析(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. final在Java中是一个保留的关键字,可以声明成员变 ...

  4. 深入分析Java中的关键字static

    深入分析Java中的关键字static 一.static关键字的基本用法 1.static关键字基本概念 方便在没有创建对象的情况下来进行调用.也就是说:被static关键字修饰的不需要创建对象去调用 ...

  5. java system.nanotime_java中的System.nanoTime与System.currentTime

    ns(nanosecond):纳秒, 时间单位.一秒的10亿分之一,即等于10的负9次方秒.常用作 内存读写速度的单位,其前面数字越小则表示速度越快. 1纳秒=1000 皮秒 1纳秒 =0.001   ...

  6. 深入分析 Java Web 中的中文编码问题

    深入分析 Java Web 中的中文编码问题 背景: 编码问题一直困扰着程序开发人员,尤其是在 Java 中更加明显,因为 Java 是跨平台的语言,在不同平台的编码之间的切换较多.接下来将介绍 Ja ...

  7. 深入分析 Java 中的中文编码问题--转

    几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言 ...

  8. 【JAVA编码专题】深入分析 Java 中的中文编码问题

    http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/ 几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么 ...

  9. 深入分析 Java 中的中文编码问题 (文章来自网络)

    许令波,developerWorks 中国网站最佳作者,现就职于淘宝网,是一名 Java 开发工程师.对大型互联网架构设计颇感兴趣,喜欢钻研开源框架的设计原理.有时间将学到的知识整理成文章,也喜欢记录 ...

最新文章

  1. Web.xml配置详解之context-param
  2. 稳扎稳打Silverlight(17) - 2.0数据之详解DataGrid, 绑定数据到ListBox
  3. Excel单样本T检验
  4. STM32使用IIC总线通讯协议在OLED屏幕上显示字符串、汉字、图像(硬件IIC)
  5. Linux系统编程8:入门篇之简单明了说明如何在Linux中Git提交代码
  6. java 拷贝属性值_Java 反射拷贝相同的属性值到指定对象中(两种实现方式)
  7. 9025.计算机专业英语,计算机专业英语测试
  8. 教你手写Java层handler机制
  9. ITOP4412开发板学习前的准备2 -- 安装ADB驱动
  10. 在计算机网络中url的含义是,计算机中URL是指什么
  11. Contiki开发日记·1——Instant-contiki环境搭建
  12. 云计算工程师必备技能图谱
  13. 如何创建springboot工程?springboot中的静态资源如何处理?
  14. Nginx最新教程通俗易懂
  15. JAVA洛谷B2117 整理药名
  16. 数据传输过程加密方案
  17. 如何去掉行首行尾的空格
  18. STC89C52单片机串口通信以及代码演示
  19. docker安装nginx kong konga
  20. 基于WIN32 API界面编程实现的华容道小游戏

热门文章

  1. post请求需要加密吗_Python接口自动化Requets之http请求(2)
  2. ubuntu执行编译好的文件显示文件不存在_嵌入式开发 | 什么是交叉编译(CROSS_COMPILE)...
  3. sql和python的区别_数据处理简单对比:Excel,SQL,Python
  4. 微信小程序封装storage(含错误处理)
  5. 设计模式之工厂模式(Factory)(3)
  6. NOI2013矩阵游戏
  7. Tomcat无法访问中文路径的解决办法
  8. centos7下nginx配置
  9. Django 基础教程
  10. 手机app常见bug积累