zoukankan      html  css  js  c++  java
  • Java之System、Runtime类

    JDK 8

    Eclipse Version: 2021-03 (4.19.0)

    ---

    都位于java.lang包下,java.lang.System、java.langRuntime(位于 rt.jar)

    public final class System {...}
    public class Runtime {...}

    目录

    System类

    Runtime类

    参考文档

    System类

    System下有下面的公开对象和方法:

    常用:

    out

    public final static PrintStream out = null;

    使用out的 print、println、printf 输出内容到 控制台,其中,print 不自动换行,printf自定义格式。

    当然,除了上面的print函数,还有 append、write、flush、close等。

    注意,执行 close 函数后,out对象就不会输出内容到 控制台了,因为 被关闭了。

    测试out
    		System.out.print("1.a");
    		System.out.println("2.ab");
    		PrintStream ps = System.out.printf("3.%s", "abc");
    		ps.append("4.-append");
    		
    		System.out.println();
    		
    		ps.write(12);
    		ps.write(65);
    		ps.write(66);
    		ps.write(67);
    		ps.write(123);
    		ps.flush();
    
    		System.out.println();
    		
    		System.out.println("关闭前:");
    		
    		ps.close();
    		
            // 没有输出
    		System.out.println("关闭后.");
    /*
    // 测试结果:
    1.a2.ab
    3.abc4.-append
    ABC{
    关闭前:
    
    */

    arraycopy(Object, int, Object, int, int)

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

    数组拷贝,但src、dest都是Object(WHY?)。

    测试arraycopy
    		// arraycopy 测试
    		final int size = 5;
    		byte[] src = new byte[] {1,2,4,8,16};
    		byte[] dest = new byte[size];
    		System.out.println("拷贝前dest:");
    		for (int i=0; i<size; i++) {
    			System.out.println("dest[" + i + "]=" + dest[i]);
    		}
    		System.arraycopy(src, 0, dest, 0, dest.length);
    		System.out.println("拷贝后dest:");
    		for (int i=0; i<size; i++) {
    			System.out.println("dest[" + i + "]=" + dest[i]);
    		}
    		
    		// 发生异常
    		System.arraycopy(src, 0, dest, 0, dest.length + 1);
    
    /*
    // 执行结果
    拷贝前dest:
    dest[0]=0
    dest[1]=0
    dest[2]=0
    dest[3]=0
    dest[4]=0
    拷贝后dest:
    dest[0]=1
    dest[1]=2
    dest[2]=4
    dest[3]=8
    dest[4]=16
    Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
    	at java.lang.System.arraycopy(Native Method)
    	at aug.Test081001.testSystem(Test081001.java:52)
    	at aug.Test081001.main(Test081001.java:11)
    
    */

    疑问:对象数组拷贝 如何,是 浅拷贝还是 深拷贝?

    测试arraycopy-对象数组
    class Abc {
    
    	public Abc(String name) {
    		super();
    		this.name = name;
    	}
    
    	/**
    	 * 属性name
    	 */
    	private String name;
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    	
    }
    
    
    // 主函数
    		// 拷贝对象数组:浅拷贝、深拷贝?
    		Abc[] arr1 = new Abc[] {new Abc("name1"), new Abc("name2")};
    		Abc[] arr2 = new Abc[2];
    		System.out.println("拷贝前:");
    		for (int i=0; i<2; i++) {
    			System.out.println("arr1[" + i + "]=" + arr1[i]);
    			System.out.println("arr2[" + i + "]=" + arr2[i]);
    		}
    		System.out.println("拷贝后:");
    		System.arraycopy(arr1, 0, arr2, 0, arr2.length);
    		for (int i=0; i<2; i++) {
    			System.out.println("arr1[" + i + "]=" + arr1[i]);
    			System.out.println("arr2[" + i + "]=" + arr2[i]);
    		}
    
    
    /*
    // 测试结果:浅拷贝!执行拷贝后,src、dest数组存了相同的对象
    拷贝前:
    arr1[0]=aug.Abc@816f27d
    arr2[0]=null
    arr1[1]=aug.Abc@87aac27
    arr2[1]=null
    拷贝后:
    arr1[0]=aug.Abc@816f27d
    arr2[0]=aug.Abc@816f27d
    arr1[1]=aug.Abc@87aac27
    arr2[1]=aug.Abc@87aac27
    */
            

    currentTimeMillis() & nanoTime()

    测试Time
    		System.out.println(System.currentTimeMillis());
    		System.out.println(System.nanoTime());
    
    /*
    // 测试结果
    1628585409683
    721089123470600
    */

    currentTimeMillis 可以转换为 当前时间——年月日时分秒,

    nanoTime 和 时钟时间无关,但可以用来计算 系统流逝的时间,比如,一个程序执行花了多少 纳秒。

    注:

    ns(nanosecond):纳秒,时间单位。一秒的十亿分之一,等于10的负9次方秒(1 ns = 10 s)。

    getenv() & getenv(String)

    获取环境变量。

    在Windows系统中,可以获取到 配置的 所有环境变量。

    测试期间发现一个小问题,打开IDE(Eclipse)后,修改、添加环境变量,此时获取不到,但重启IDE后就可以获取到了。

    public static java.util.Map<String,String> getenv() {
    //...
    }
    
    public static String getenv(String name) {
    //...
    }
    

    注:底层使用 ProcessEnvironment类-非public 实现。

    注:对于同一个程序,可能环境变量不同,其执行的行为也不一定相同,实现一定的控制作用。

    测试环境变量
    		Consumer<Object> cs = System.out::println;
    		cs.accept(">>>>>System->env:");
    		Map<String, String> env = System.getenv();
    		env.forEach((k,v)->{
    			cs.accept("key=" + k + ", val=" + v);
    		});

    getProperties() & getProperty(String) & getProperty(String, String)

    getProperties源码
        // System properties.
        public static Properties getProperties() {
            SecurityManager sm = getSecurityManager();
            if (sm != null) {
                sm.checkPropertiesAccess();
            }
    
            return props;
        }
        
        // System properties.
        private static Properties props;
        // 本地方法
        private static native Properties initProperties(Properties props);

    系统属性,使用本地方法进行初始化。

    包括但不限于下面的属性:

    部分系统属性
    key=java.runtime.name, val=Java(TM) SE Runtime Environment
    key=sun.boot.library.path, val=D:Program FilesJavajdk1.8.0_202jrein
    key=java.vm.version, val=25.202-b08
    key=abcd, val=99999
    key=java.vm.vendor, val=Oracle Corporation
    key=java.vendor.url, val=http://java.oracle.com/
    key=path.separator, val=;
    key=java.vm.name, val=Java HotSpot(TM) 64-Bit Server VM
    key=file.encoding.pkg, val=sun.io
    key=java.runtime.version, val=1.8.0_202-b08
    key=java.class.path, val=D:WSews21apr	argetclasses;D:workmvnrepoorgprojectlomboklombok1.18.20lombok-1.18.20.jar
    key=java.vm.specification.version, val=1.8
    ...

    还可以自定义属性。

    Eclipse中添加如下 VM参数即可:

    通过系统属性 可以得到 ddd、abcd的值。

    疑问:既有环境变量,又有系统属性,在开发程序时,要是两者有相同的变量,应该听谁的呢?需要设定优先级才是。

    除了添加,还有 设置系统属性函数 setProperties、setProperty,程序设置后,前面IDE里面配置的 ddd、abcd还有效吗?

    测试系统属性获取&设置
    		cs.accept(">>>>>System->Properties:");
    		Properties props = System.getProperties();
    		props.keySet().forEach(key->{
    			cs.accept("key=" + key + ", val=" + props.getProperty((String) key));
    		});
    		
    		System.setProperty("ddd", "in main");
    		System.setProperty("abcd", "in main");
    		
    		Properties props2 = System.getProperties();
    		props2.keySet().forEach(key->{
    			cs.accept("key=" + key + ", val=" + props2.getProperty((String) key));
    		});

    测试结果:

    程序中的设置生效了,而Eclipse的VM arguments中配置的无效——被覆盖了。

    key=abcd, val=in main
    key=ddd, val=in main

    命令行的先被设置,然后,程序里面执行了设置,所以,变更了,没问题。

    identityHashCode(Object)

    一致hash函数。

    对象的hashCode函数可以被修改,重写,返回的hashCode会变化,,但这个 identityHashCode 却不会,可以用来判断 两个对象是否是同一个——调用这个值的返回值相同。

    类没有重写 hashCode函数时,两个函数返回的相同:

    Abc obj1 = new Abc("n1");
    System.out.println(obj1.hashCode());
    System.out.println(System.identityHashCode(obj1));
    执行结果:
    135721597
    135721597

    重写Abc类的hashCode函数:

    	// Abc类下有一个 String类型的 name属性
        @Override
    	public int hashCode() {
    		if (this.name == null) {
    			return 0;
    		}
    		
    		return this.name.hashCode();
    	}
        
    再次执行结果:
    3459
    135721597

    可以用 十六进制打印出来:

    System.out.printf("0x%08x", System.identityHashCode(obj1));

    未使用:

    getSecurityManager()

    inheritedChannel()

    load(String)

    loadLibrary(String)

    mapLibraryName(String)

    exit(int)

    Runtime类

    Runtime下有下面的公开对象和方法:

    源码中如是说:每个Java应用都有一个唯一的 Runtime实例...

    Runtime源码注释
    /**
     * Every Java application has a single instance of class
     * <code>Runtime</code> that allows the application to interface with
     * the environment in which the application is running. The current
     * runtime can be obtained from the <code>getRuntime</code> method.
     * <p>
     * An application cannot create its own instance of this class.
     *
     * @author  unascribed
     * @see     java.lang.Runtime#getRuntime()
     * @since   JDK1.0
     */

    常用(用过):

    getRuntime()

    获取这个Java应用的Runtime实例,第一步

    获取后,就可以调用 下面的实例方法了。

    和System不同,这个类下面 还有 getRuntime() 是 类方法,其它公开的都是 实例方法。

    addShutdownHook(Thread) & removeShutdownHook(Thread)

    最近接触到这个 addShutdownHook 方法,用来在 Java应用 关闭的时候 执行一个线程里面的内容。

    至于removeShutdownHook 方法,暂未使用过。

    测试程序1:removeShutdownHook 无效!其remove的Thread和 addShutdownHook的不是同一个。

    	public static void main(String[] args) {
    		Runtime rt = Runtime.getRuntime();
    		System.out.println(rt.availableProcessors());
    		
    		System.out.println(rt.maxMemory());
    		System.out.println(rt.totalMemory());
    		System.out.println(rt.freeMemory());
    		System.out.println(rt.totalMemory() - rt.freeMemory());
    		
    		rt.addShutdownHook(new Thread(()->{
    			try {
    				Thread.sleep(5000);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			System.out.println("int addShutdownHook. now=" + new Date());
    		}));
    		
    		rt.removeShutdownHook(new Thread(()->{
    			try {
    				Thread.sleep(3000);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			System.out.println("in removeShutdownHook. now=" + new Date());
    			
    		}));
    		
    		System.out.println("main end. now=" + new Date());
    	}

    执行结果:

    8
    119537664
    64487424
    63144640
    1342784
    main end. now=Tue Aug 10 18:09:48 CST 2021
    int addShutdownHook. now=Tue Aug 10 18:09:53 CST 2021

    改造后的程序:removeShutdownHook 生效了

    使用removeShutdownHook
    	public static void main(String[] args) {
    		Runtime rt = Runtime.getRuntime();
    		System.out.println(rt.availableProcessors());
    		
    		System.out.println(rt.maxMemory());
    		System.out.println(rt.totalMemory());
    		System.out.println(rt.freeMemory());
    		System.out.println(rt.totalMemory() - rt.freeMemory());
    		
    		Thread td = new Thread(()->{
    			try {
    				Thread.sleep(5000);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			System.out.println("int addShutdownHook. now=" + new Date());
    		});
    		
    		rt.addShutdownHook(td);
    		
    		new Thread(()->{
    			try {
    				// 3秒
    				Thread.sleep(3000);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			Runtime.getRuntime().removeShutdownHook(td);
    			System.out.println("int removeShutdownHook. now=" + new Date());
    		}).start();
    		
    		System.out.println("main end. now=" + new Date());
    	}

    执行结果:

    8
    119537664
    64487424
    63144640
    1342784
    main end. now=Tue Aug 10 18:13:53 CST 2021
    int removeShutdownHook. now=Tue Aug 10 18:13:56 CST 2021

    availableProcessors()

    Java应用可用的 处理器核心 数量。

    注:在虚拟机、Docker中运行时,可以更改 程序使用的核心数量。

    freeMemory() & maxMemory() & totalMemory()

    返回内存信息,单位字节,堆内存信息,可以通过 Xms、Xmx 来设置。

    测试memory
    System.out.println(rt.maxMemory());
    		System.out.println(rt.totalMemory());
    		System.out.println(rt.freeMemory());
    		System.out.println(rt.totalMemory() - rt.freeMemory());
    
    // 执行结果
    1883242496
    128974848
    126929816
    2045032
    
    // 设置 -Xms64m -Xmx128m 后
    // 执行结果
    119537664
    64487424
    63144640
    1342784
    

    exec(...)

    执行系统命令,比如,Linux系统的ls命令(Windows的dir),或者,执行某个其它语言编写的程序,比如,Python、GO开发的。

    执行后,返回结果,再对结果进行分析。

    Linux 使用 sh -c,Windows 使用 cmd /c。

    在Windows上的测试:

    		// 测试exec
    		try {
    			// Windows 10
    			Process ps = rt.exec("cmd /c dir c:");
    			try (InputStream is = ps.getInputStream()) {
    				InputStreamReader isr = new InputStreamReader(is);
    				BufferedReader br = new BufferedReader(isr);
    				String ret = null;
    				while ((ret = br.readLine()) != null) {
    					System.out.println(ret);
    				}
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}

    执行结果:存在一些乱码,是一些中文没有做转换

    未使用:

    runFinalizersOnExit(boolean)

    halt(int)

    exit(int)

    load(String)
    loadLibrary(String)

    traceInstructions(boolean)
    traceMethodCalls(boolean)

    参考文档

    1、Java Runtime的使用

    2、JVM调优总结 -Xms -Xmx -Xmn -Xss

    3、IOException: 系统找不到指定的文件,java调用可执行程序

    4、

  • 相关阅读:
    670. Maximum Swap
    126. Word Ladder II
    695. Max Area of Island
    689. Maximum Sum of 3 Non-Overlapping Subarrays
    667. Beautiful Arrangement II
    前端开发-css
    前端开发-html
    mysql补充
    pythonl操作数据库
    mysql索引原理
  • 原文地址:https://www.cnblogs.com/luo630/p/15124550.html
Copyright © 2011-2022 走看看