7.2 系统相关 7.2.1 System类

7.2 系统相关

Java程序在不同操作系统上运行时,可能需要取得平台相关的属性,或者调用平台命令来完成特定功能。Java提供了System类和Runtime类来与程序的运行平台进行交互。

7.2.1 System类

System类代表当前Java程序的运行平台,程序不能创建System类的对象, System类提供了一些类变量类方法,允许直接通过System类来调用这些类变量和类方法。
System类提供了代表标准输入标准输出错误输出类变量,并提供了一些静态方法用于访问环境变量系统属性的方法,还提供了加载文件动态链接库的方法。

加载文件和动态链接库

加载文件和动态链接库主要对native方法有用,对于一些特殊的功能(如访问操作系统底层硬件设备等)Java程序无法实现,必须借助C语言来完成,此时需要使用C语言Java方法提供实现。

其实现步骤如下:

  1. Java程序中声明native修饰的方法,类似于abstract方法,只有方法签名,没有实现。编译该Java程序,生成一个class文件。
  2. javah编译第1步生成的class文件,将产生一个.h文件
  3. 写一个cpp文件实现native方法,这一步需要包含第2步产生的.h文件(这个.h文件中又包含了JDK带的jni.h文件)
  4. Java中用System类的loadLibrary()方法或Runtime类的loadLibrary()方法加载第4步产生的动态链接库文件,Java程序中就可以调用这个native方法了。

访问环境变量和系统属性

下面程序通过System类来访问操作的环境变量系统属性

  1. 通过调用System类的getenv()方法可以访问程序所在平台的环境变量
  2. 通过getProperties()getProperty()方法可以访问程序所在平台的系统属性.

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

import java.io.*;
import java.util.*;

public class SystemTest {
public static void main(String[] args) throws Exception {
// 获取系统所有的环境变量
Map<String, String> env = System.getenv();
// 遍历输出所有的环境遍历
for (String name : env.keySet()) {
System.out.println(name + " ---> " + env.get(name));
}
// 获取指定的环境变量
System.out.println("-----------------------------------------------");
String[] envKeys = { "JAVA_HOME", "CLASSPATH" };
for (int i = 0; i < envKeys.length; i++) {
System.out.println(envKeys[i] + " ---> " + System.getenv(envKeys[i]));
}
System.out.println("-----------------------------------------------");

// 获取所有的系统属性
Properties props = System.getProperties();
// 将所有系统属性保存到props.txt文件中
props.store(new FileOutputStream("props.txt"), "System Properties");
// 输出特定的系统属性
System.out.println(System.getProperty("os.name"));
}
}

控制台部分输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
......
M2_HOME ---> D:\dev\apache-maven-3.5.4
ProgramFiles ---> C:\Program Files
......
OS ---> Windows_NT
......
TEMP ---> C:\Users\lan\AppData\Local\Temp
......
-----------------------------------------------
JAVA_HOME ---> E:\Java8\Java\jdk1.8.0_131
CLASSPATH ---> .;E:\Java8\Java\jdk1.8.0_131\lib\dt.jar;E:\Java8\Java\jdk1.8.0_131\lib\toos.jar;E:\dev2\AspectJ1.9.4\lib\aspectjrt.jar;E:\dev2\junit\junit-4.12.jar;
-----------------------------------------------
Windows 10

生成的props.txt文件部分内容:

1
2
3
4
5
6
7
8
9
10
11
#System Properties
#Mon Sep 30 13:34:28 CST 2019
java.runtime.name=Java(TM) SE Runtime Environment
sun.boot.library.path=E\:\\Java8\\Java\\jdk1.8.0_131\\jre\\bin
java.vm.version=25.131-b11
java.vm.vendor=Oracle Corporation
java.vendor.url=http\://java.oracle.com/
.......
sun.desktop=windows
sun.cpu.isalist=amd64

垃圾回收相关方法

System

  • 提供gc()方法用来通知系统进行垃圾回收,
  • 提供runFinalization()方法用来通知系统调用finalize()方法来进行资源清理

获取当前时间的方法

currentTimeMillis()nanoTime(),它们都返回一个long整数。实际上它们都返回当前时间与UTC1970年1月1日 0点整的时间差,前者以毫秒作为单位,后者以纳秒作为单位。

必须指出的是,这两个方法返回的时间粒度取决于底层操作系统,可能所在的操作系统根本不支持以毫秒、纳秒作为计时单位。
例如,许多操作系统以几十毫秒为单位测量时间,这种情况下currentTimeMillis()方法不可能返回精确的毫秒数:
nanoTime()方法很少用,因为大部分操作系统都不支持使用纳秒作为计时单位

标准输入输出相关的属性和方法

除此之外, System类的inouterr分别代表系统的标准输入标准输出错误输出流,其中,标准输入通常是键盘,标准输出通常是显示器

提供了setIn()setOut()setErr()方法来改变系统的标准输入、标准输出和标准错误输出流。

identityHashCode方法

System类还提供了一个identityHashCode(Object x)方法,该方法返回指定对象的精确hashCode值,也就是根据该对象的地址计算得到的hashCode值。

不同对象的identityHashCode值一定不同

当某个类的hashCode()方法被重写后,该类实例的hashCode()方法就不能唯一地标识该对象;但通过identityHashCode()方法返回的hashCode值,依然是根据该对象的地址计算得到的hashCode值。不同的对象在内存中的地址不可能相同,所以,如果两个对象的identityHashCode值相同,则两个对象绝对是同一个对象

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class IdentityHashCodeTest {
public static void main(String[] args) {
// 下面程序中s1和s2是两个不同对象
String s1 = new String("Hello");
String s2 = new String("Hello");
// String重写了hashCode()方法——改为根据字符序列计算hashCode值,
// 因为s1和s2的字符序列相同,所以它们的hashCode方法返回值相同
System.out.println(s1.hashCode() + "----" + s2.hashCode());

// s1和s2是不同的字符串对象,所以它们的identityHashCode值不同
System.out.println(System.identityHashCode(s1) + "----" + System.identityHashCode(s2));
// 相同的字符串直接量放在常量池中,是同一个对象
String s3 = "Java";
String s4 = "Java";

// s3和s4是相同的字符串对象,所以它们的identityHashCode值相同
System.out.println(System.identityHashCode(s3) + "----" + System.identityHashCode(s4));
}
}

运行结果:

1
2
3
69609650----69609650
366712642----1829164700
2018699554----2018699554