zoukankan      html  css  js  c++  java
  • 6.2 系统相关


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

    一、System类——java.lang.System

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

    1、访问环境变量和系统属性

    
    import java.io.*;
    import java.util.*;
    
    public class SystemTest
    {
    	public static void main(String[] args) throws Exception
    	{
    		// 获取系统所有的环境变量
    		Map<String, String> env = System.getenv();
    		for (var name : env.keySet())
    		{
    			System.out.println(name + " ---> " + env.get(name));
    		}
    		// 获取指定环境变量的值
    		System.out.println(System.getenv("JAVA_HOME"));
    		// 获取所有的系统属性
    		Properties props = System.getProperties();
    		// 将所有系统属性保存到props.txt文件中
    		props.store(new FileOutputStream("props.txt")
    			, "System Properties");
    		// 输出特定的系统属性
    		System.out.println(System.getProperty("os.name"));
    	}
    }
    ...
    CommonProgramFiles(x86) ---> C:Program Files (x86)Common Files
    ProgramFiles ---> C:Program Files
    PUBLIC ---> C:UsersPublic
    NUMBER_OF_PROCESSORS ---> 4
    windir ---> C:Windows
    =:: ---> ::
    D:Javajdk-12
    Windows 10
    

    2、加载文件和动态链接库

    加载文件和动态链接库主要对native方法有用,对一些特殊功能(如访问系统的底层硬件设备等)需要借助C语言来完成,此时需要C语言为Java方法提供实现:
    (1)native方法只有签名没有实体。需要使用javax -h来编译该Java程序,将生成一个.h头文件和.class文件。
    (2)写一个.cpp文件实现native方法,需要包含(1)中生成的.h文件(这个.h文件又包含JDK自带的jin.h文件)。
    (3)将第(2)步的.cpp文件编译成动态链接库文件。
    (4)在Java中用System类的loadLibrary..()方法或Runtime类的loadLibrary()方法加载第3步生成的动态链接库文件,java程序就可以调用这个native方法啦。

    3、垃圾回收方法gc()和通知系统进行资源清理的runFinalization()

    在垃圾回收机制回收垃圾对象之前,总会先调用它的finalization()方法,该方法可能导致对象重新获得引用,从而导致垃圾回收机制取消回收。

    class  GcTest
    {
    	public static void main(String[] args) 
    	{
    		for (int i=0;i<4 ;i++ )
    		{
    			new GcTest();//创建了对象但是没有引用,等待垃圾回收机制回收
    			System.gc();//强制系统进行垃圾回收
    			//Rumtime.getRuntime.gc();
    		}
    	}
    	@Override
    	public void finalize()
    	{
    		System.out.println("系统正在清理GcTest对象的资源");
    	}
    }
    ---------- 运行Java捕获输出窗 ----------
    系统正在清理GcTest对象的资源
    系统正在清理GcTest对象的资源
    
    输出完成 (耗时 0 秒) - 正常终止
    

    4、获取系统当前时间

    currentTimeMillis()和nanoTime(),它们都返回long型整数。代表的是当前时间与UTC 1970年1月1日午夜的时间差,前者以毫秒(1ms=10-3s)为单位,后者以微秒(1ns=10-9s)为单位。
    这两个方法返回时间粒度取决与底层操作系统,可能所在的操作系统不支持以毫秒、纳秒作为计时单位。

    //import java.lang.System;
    //import java.lang.Math;
    class SystemTimeTest 
    {
    	public static void main(String[] args) 
    	{
    		long t=System.currentTimeMillis();
    		System.out.println(t);
    		double year=t/(Math.pow(10,3)*3600*24*365)+1970;
    		System.out.println(year);
    	}
    }
    ---------- 运行Java捕获输出窗 ----------
    1583902307999
    2020.225212709253
    
    输出完成 (耗时 0 秒) - 正常终止
    

    5、标准输入输出、错误输出流

    System类的in、out、err分别代表标准输入(通常是键盘)、标准输出(显示器)、错误输出流,并提供setIn()、setOut()、setErr()来改变系统的标准输入、标准输出和错误输出流。以后介绍

    6、 对象的精确hashCode值

    System.identityHashCode(Object x)方法,该方法返回指定对象精确的hashCode值,根据该对象的地址计算得到的hashCode值。当某个对象hashCode()方法被重写了,该方法依然可以获得它的hashCode值。如果两个对象的identityHashCode值相同,则它们指向同一个对象。

    
    public class IdentityHashCodeTest
    {
    	public static void main(String[] args)
    	{
    		// 下面程序中s1和s2是两个不同对象
    		var s1 = new String("Hello");
    		var 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));
    		var s3 = "Java";
    		var s4 = "Java";
    		// s3和s4是相同的字符串对象,所以它们的identityHashCode值相同
    		System.out.println(System.identityHashCode(s3)
    			+ "----" + System.identityHashCode(s4));
    	}
    }
    ---------- 运行Java捕获输出窗 ----------
    69609650----69609650
    1826771953----1406718218
    245257410----245257410
    
    输出完成 (耗时 0 秒) - 正常终止
    

    二、Runtime类和Java 9的ProcessHandle

    Runtime类代表Java程序的运行环境,每个Java程序都有一个与之对应的Runtime实例,运用程序通过该对象与之相连。应用程序不能创建自己的Rumtime实例,但可以通过getRumtime()方法获取与之相关联的Rumtime对象。
    Runtime类也提供了gc()方法和runFinalization()方法通知系统进行垃圾回收、清理系统资源,并提供了load(String filename)和loadLibrary(String libname)方法来加载文件和动态链接库。

    1、访问JVM的运行环境

    Runtime类代表Java程序运行环境,可以访问JVM的相关信息,如处理器数量、内存信息等。如下程序

    public class RuntimeTest
    {
    	public static void main(String[] args)
    	{
    		//获取Java程序关联的运行对象
    		var rt=Runtime.getRuntime();
    		System.out.println("处理器的数量:"+rt.availableProcessors());
    		System.out.println("空闲的内存数:"+rt.freeMemory());
    		System.out.println("总内存数:"+rt.totalMemory());
    		System.out.println("可用最大内存数:"+rt.maxMemory());
    	}
    }
    ---------- 运行Java捕获输出窗 ----------
    处理器的数量:4
    空闲的内存数:199982344
    总内存数:201326592
    可用最大内存数:3198156800
    
    输出完成 (耗时 0 秒) - 正常终止
    

    2、单独启动一个进程来运行操作系统命令

    class  ExecTest
    {
    	public static void main(String[] args) 
    		throws Exception
    	{
    		var rt=Runtime.getRuntime();
    		//运行记事本程序
    		rt.exec("notepad.exe");
    	}
    }
    

    上述代码将会启动windows系统的记事本程序。Runtime()提供了一系列的exec()方法来运行操作系统命令。

    3、进程相关

    通过exec启动平台命令后,他会变成一个进程,Java使用Process代表进程。Java 9新增了ProcessHand接口,通过该接口可以获得进程的ID、父进程和后代进程;通过接口的onExit()方法可在进程结束时完成某些行为。

    
    import java.util.concurrent.*;
    public class ProcessHandleTest
    {
    	public static void main(String[] args)
    		throws Exception
    	{
    		var rt = Runtime.getRuntime();
    		// 运行记事本程序
    		Process p = rt.exec("notepad.exe");
    		ProcessHandle ph = p.toHandle();
    		System.out.println("进程是否运行: " + ph.isAlive());
    		System.out.println("进程ID: " + ph.pid());
    		System.out.println("父进程: " + ph.parent());
    		// 获取ProcessHandle.Info信息
    		ProcessHandle.Info info = ph.info();
    		// 通过ProcessHandle.Info信息获取进程相关信息
    		System.out.println("进程命令: " + info.command());
    		System.out.println("进程参数: " + info.arguments());
    		System.out.println("进程启动时间: " + info.startInstant());
    		System.out.println("进程累计运行时间: " + info.totalCpuDuration());
    		// 通过CompletableFuture在进程结束时运行某个任务
    		CompletableFuture<ProcessHandle> cf = ph.onExit();
    		cf.thenRunAsync(()->{
    			System.out.println("程序退出");
    		});
    		Thread.sleep(5000);
    	}
    }
    ---------- 运行Java捕获输出窗 ----------
    进程是否运行: true
    进程ID: 6192
    父进程: Optional[6804]
    进程命令: Optional[C:WindowsSystem32
    otepad.exe]
    进程参数: Optional.empty
    进程启动时间: Optional[2020-03-11T07:27:38.006Z]
    进程累计运行时间: Optional[PT0.125S]
    
    输出完成 (耗时 6 秒) - 正常终止
    
  • 相关阅读:
    progID
    windbg
    msil_accessibility_b03f5f7f11d50a3a_6.1.7600.16385_none_2232298e4f48d6ba
    jupybook编程快捷键
    django遇到的error(待续)
    python 遇到error(待续)
    前端 遇到error(待续)
    sql语句组件 在框架中的应用
    django models分页
    Python的学习之旅———用户与程序交互
  • 原文地址:https://www.cnblogs.com/weststar/p/12461738.html
Copyright © 2011-2022 走看看