`
salever
  • 浏览: 254200 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java.lang.System类浅析

阅读更多

本文同步发表在 http://www.xeclipse.com/?p=1300

最近又抽空看了一下java的System类,发现了一些有意思的地方,做一个简单的整理吧,免得忘记了。

public final class System extends Object

 

System 类包含一些有用的类字段和方法。它不能被实例化。

在 System 类提供的设施中,有标准输入、标准输出和错误输出流;对外部定义的属性和环境变量的访问;加载文件和库的方法;还有快速复制数组的一部分的实用方法。

以上源自JDK 6.0的官方API说明,这里分享一下个人的理解。

这个类有几个比较重要的方法,比如

static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) 

static long currentTimeMillis() 

static Map<String,String> getenv()  

static Properties getProperties()  

static void loadLibrary(String libname)  

static long nanoTime()
  

下面一一讲解一下:

计时

currentTimeMillis()  返回以毫秒为单位的当前时间。

nanoTime()  返回最准确的可用系统计时器的当前值,以毫微秒为单位。

这2个方法的区别很大,并非仅仅只是时间精度的区别。currentTimeMillis() 返回当前时间,而nanoTime() 只是返回一个毫微妙级别的数字,并非代表当前的系统时间。但是可以用返回的结果查进行经确定时。

	long nanoTime1 = System.nanoTime();
		long timeMillis1 = System.currentTimeMillis();
		System.out.println("System.nanoTime():" + nanoTime1);
		System.out.println("System.currentTimeMillis(): " + timeMillis1);

 

输出结果:

System.nanoTime():117701429470021
System.currentTimeMillis(): 1343123446809

 

并非只是差了10^6次方。

下面会讲到如何用nanoTime来进行准备计时。

数据复制

arraycopy(Object src, int srcPos, Object dest, int destPos, int length)  从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。

这是一个很常用的方法,平时用到过,但是没怎么注意它的实现,结果上次就遇到一个小尴尬。按照一般来说,Java中的数组复制有2种情况,浅复制和深复制。前者就不必再赘述了,后者其实就是对元素的单独复制,2个数组之间不存在引用关系。

int size = 100000;
		int[] sources = new int[size];
		int[] destination = new int[size];

		for (int index = 0; index < size; index++) {
			destination[index] = sources[index];
		}

		long nanoTime2 = System.nanoTime();
		long timeMillis2 = System.currentTimeMillis();
		System.out.println("User array copy takes : " + (nanoTime2 - nanoTime1)
				+ " in ns.");
		System.out.println("User array copy takes : "
				+ (timeMillis2 - timeMillis1) + " in ms");

		System.arraycopy(sources, 0, destination, 0, size);

		long nanoTime3 = System.nanoTime();
		long timeMillis3 = System.currentTimeMillis();
		System.out.println("System array copy takes : "
				+ (nanoTime3 - nanoTime2) + " in ns.");
		System.out.println("System array copy takes : "
				+ (timeMillis3 - timeMillis2) + " in ms");

 

这里对100000个整型数组进行复制,分别采用数组复制和System的复制,看看结果:

User array copy takes : 2470705 in ns.
User array copy takes : 2 in ms
System array copy takes : 148977 in ns.
System array copy takes : 1 in ms

 

这里System的arrayCopy几乎要快一倍。

换几个值测试一下:

10000(1万)的情况

User array copy takes : 634974 in ns.
User array copy takes : 1 in ms
System array copy takes : 158578 in ns.
System array copy takes : 0 in ms

 

1000000(1百万)的情况

User array copy takes : 13381801 in ns.
User array copy takes : 13 in ms
System array copy takes : 1432499 in ns.
System array copy takes : 2 in ms

 

100000000(1千万)

User array copy takes : 72962115 in ns.
User array copy takes : 73 in ms
System array copy takes : 12106224 in ns.
System array copy takes : 12 in ms
 

 

对比一下知道了,System的arrayCopy要快很多。

为什么呢,看看方法的实现去:

  public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

 

JNI实现,我觉得应该是使用了指针的移动进行计算的。不确定。。。

获取系统信息

getProperties()  确定当前的系统属性。

getenv()  返回一个不能修改的当前系统环境的字符串映射视图。

这里的2个方法都是获取系统信息的,一个是系统的一些属性信息,一个是系统环境变量。不过对于系统属性来说,Java提供了在当前JVM生命周期内临时修改的方法,

setProperty(String key, String value) 设置指定键指示的系统属性。

先看看getProperties():

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 用户的当前工作目录

输出地结果为:写道

{java.runtime.name=Java(TM) SE Runtime Environment, sun.boot.library.path=C:\Java\jdk1.6.0_17\jre\bin, java.vm.version=14.3-b01, java.vm.vendor=Sun Microsystems Inc., java.vendor.url=http://java.sun.com/, path.separator=;, java.vm.name=Java HotSpot(TM) Client VM, file.encoding.pkg=sun.io, sun.java.launcher=SUN_STANDARD, user.country=US, sun.os.patch.level=, java.vm.specification.name=Java Virtual Machine Specification, user.dir=E:\workspace\common_ws\org.salever.j2se.common, java.runtime.version=1.6.0_17-b04, java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment, java.endorsed.dirs=C:\Java\jdk1.6.0_17\jre\lib\endorsed, os.arch=x86, java.io.tmpdir=C:\Users\LiXP\TEMP\, line.separator=
, java.vm.specification.vendor=Sun Microsystems Inc., user.variant=, os.name=Windows 7, sun.jnu.encoding=GBK, java.library.path=C:\Java\jdk1.6.0_17\bin;.;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;F:\IBM\WebSphere MQ\Java\lib;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Java\jdk1.6.0_17\bin;D:\Program Files\TortoiseSVN\bin;D:\library\apache-maven-3.0.3\bin;F:\IBM\WebSphere MQ\bin;F:\IBM\WebSphere MQ\tools\c\samples\bin;C:\Program Files\MySQL\MySQL Server 5.1\bin;D:\library\apache-ant-1.8.2/bin;C:\Program Files\Bitvise Tunnelier, java.specification.name=Java Platform API Specification, java.class.version=50.0, sun.management.compiler=HotSpot Client Compiler, os.version=6.1, user.home=C:\Users\LiXP, user.timezone=, java.awt.printerjob=sun.awt.windows.WPrinterJob, file.encoding=UTF-8, java.specification.version=1.6, java.class.path=E:\workspace\common_ws\org.salever.j2se.common\bin;E:\workspace\common_ws\org.salever.j2se.common\lib\activation.jar;E:\workspace\common_ws\org.salever.j2se.common\lib\commons-email-1.2.jar;E:\workspace\common_ws\org.salever.j2se.common\lib\mail.jar;E:\workspace\common_ws\org.salever.j2se.common\lib\jxl.jar;E:\workspace\common_ws\org.salever.j2se.common\lib\comm.jar;D:\Program Files\eclipse\plugins\org.junit_4.8.1.v4_8_1_v20100427-1100\junit.jar;D:\Program Files\eclipse\plugins\org.hamcrest.core_1.1.0.v20090501071000.jar;E:\workspace\common_ws\org.salever.j2se.common\lib\jacob.jar;E:\workspace\common_ws\org.salever.j2se.common\lib\commons-collections-3.2.1.jar;E:\workspace\common_ws\org.salever.j2se.common\lib\commons-lang-2.4.jar;E:\workspace\common_ws\org.salever.j2se.common\lib\velocity-1.6.4.jar, user.name=LiXP, java.vm.specification.version=1.0, java.home=C:\Java\jdk1.6.0_17\jre, sun.arch.data.model=32, user.language=en, java.specification.vendor=Sun Microsystems Inc., awt.toolkit=sun.awt.windows.WToolkit, java.vm.info=mixed mode, java.version=1.6.0_17, java.ext.dirs=C:\Java\jdk1.6.0_17\jre\lib\ext;C:\Windows\Sun\Java\lib\ext, sun.boot.class.path=C:\Java\jdk1.6.0_17\lib\tools.jar;C:\Java\jdk1.6.0_17\jre\lib\resources.jar;C:\Java\jdk1.6.0_17\jre\lib\rt.jar;C:\Java\jdk1.6.0_17\jre\lib\jsse.jar;C:\Java\jdk1.6.0_17\jre\lib\jce.jar;C:\Java\jdk1.6.0_17\jre\lib\charsets.jar, java.vendor=Sun Microsystems Inc., file.separator=\, java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport.cgi, sun.io.unicode.encoding=UnicodeLittle, sun.cpu.endian=little, sun.desktop=windows, sun.cpu.isalist=pentium_pro+mmx pentium_pro pentium+mmx pentium i486 i386 i86}
 

这里还有一个实时设置属性的方法,其实在Java程序启动的时候,设置的参数-D也有这个功能。

先看看一个简单的使用:

	        System.setProperty("user.home", "c:/");
		property = System.getProperty("user.home");
		System.out.println("user.home:" + property);

		property = System.getProperty("user.dir");
		System.out.println("user.dir:" + property);

		System.setProperty("user.dir", "c:/");
		property = System.getProperty("user.dir");
		System.out.println("user.dir:" + property);

		property = System.getProperty("user.newArg");
		System.out.println("user.newArg:" + property);

		System.setProperty("user.newArg", "c:/");
		property = System.getProperty("user.newArg");
		System.out.println("user.newArg:" + property);

 

其中user.home user.dir都是已知属性,而user.newArg则是新创建的,看看打印的输出:

user.home:C:\Users\LiXP
user.home:c:/
user.dir:E:\workspace\common_ws\org.salever.j2se.common
user.dir:c:/
user.newArg:null
user.newArg:c:/

 

这里将user.home和user.dir都设置为c:/,然后在user.newArg被设置为新的值c:/

类似,如果在JVM启动参数加上:写道

-Duser.home=d:/ -Duser.dir=d:/ -Duser.newArg=helloworld
 

打印的结果为:user.home:d:/

user.home:c:/
user.dir:d:/
user.dir:c:/
user.newArg:helloworld
user.newArg:c:/
 

关于-D开始的参数,参考上面得列表。

动态加载DLL类库

load(String filename) 从作为动态库的本地文件系统中以指定的文件名加载代码文件。

loadLibrary(String libname) 加载由 libname 参数指定的系统库。

这里主要用于JNI的使用,动态的加载DLL或者其他文件,关于JNI这里暂不讲述。只是提一下。System本身的很多方法都是通过JNI调用的本地方法,可想而知,JVM的实现必须要包含这些。

分享到:
评论

相关推荐

    Java学习教程-java中number类浅析.docx

    ### Java学习教程:Java中Number类浅析 #### 一、概述 在Java语言中,`Number`类作为所有基本数值类型的包装类的基础类,它提供了一系列用于处理数值的方法。这些包装类包括`Integer`、`Long`、`Byte`、`Double`、...

    浅析Java设计模式【3】——代理.pdf

    - **基于接口的动态代理**:使用 `java.lang.reflect.Proxy` 类和 `java.lang.reflect.InvocationHandler` 接口来实现。 - **基于类的动态代理(CGLIB)**:使用第三方库 CGLIB 来实现代理,适用于无法使用基于接口...

    Java中main()方法浅析.docx

    ### Java中main()方法浅析 #### 一、概述 在Java编程语言中,`main()`方法具有特殊的意义,它是所有Java应用程序的起点。当Java虚拟机(JVM)启动并加载了一个包含`main()`方法的类时,它会自动调用这个方法来开始...

    浅析Java8新特性Lambda表达式和函数式接口

    也可以包含 Java.lang.Object 里的 public 方法,因为任何一个类都继承 Object 类,包含了来自 java.lang.Object 里对这些抽象方法的实现,也不属于抽象方法。 Java 8 内置函数式接口: * 四大核心函数式接口:...

    浅析C语言、Java、Python的数组合并方法.zip

    在Java中,可以使用ArrayList或ArrayUtils(Apache Commons Lang库)来合并数组。ArrayList是一个动态数组,可以添加、删除元素。以下是使用ArrayList合并两个整数数组的示例: ```java import java.util.ArrayList...

    浅析对Java关键字final和static的理解

    例如,`java.lang.String`类就是`final`的,防止了对字符串操作的不必要的复杂性。 2. **final修饰方法**: `final`方法不能被子类重写,这保证了在继承链中的特定实现。这通常用于确保某些方法的行为在任何时候都...

    浅析java 的 static 关键字用法

    Java中的`static`关键字是Java语言中的一个重要特性,它用于定义类级别的成员,包括变量、方法、块和内部类。本文将深入解析`static`关键字的五个主要用途:静态成员变量、静态方法、静态初始化块、静态内部类以及...

    关于Java中try finally return语句的执行顺序浅析

    Exception in thread "main" java.lang.ArithmeticException: / by zero at com.becoda.bkms.bus.basics.web.Test2.test(Test2.java:15) at com.becoda.bkms.bus.basics.web.Test2.main(Test2.java:5) 可以看到,...

    浅析Java编程中枚举类型的定义与使用

    当我们使用`enum`定义一个枚举类型时,实际上创建了一个继承自`java.lang.Enum`的类。例如: ```java public enum OpConstants { TURN_LEFT, TURN_RIGHT, SHOOT } ``` 这里,`OpConstants`就是一个枚举类型,...

    浅析final,finally,finalize 的区别

    例如,`java.lang.Object` 类就是 `final` 的,因此不能有任何子类。 - **final 修饰变量**:`final` 变量是一个常量,一旦赋值后就不能再改变。这可以是类级别的静态变量或实例变量,也可以是局部变量。例如: ``...

    Android JNI 浅析

    在Java代码中,我们通常会在类的静态代码块中调用`System.loadLibrary()`方法,如`System.loadLibrary("media_jni");`,这会指示VM在运行时加载指定的动态链接库(如libmedia_jni.so)。这个过程发生在Java类被首次...

Global site tag (gtag.js) - Google Analytics