23-System(Properties)+Runtime+Process+垃圾收集(gc()/runFinalization()/finalize())

一、java.lang.System

1、public final class System:系统类,为用户程序提供当前环境下的系统资源。使用前不需要用new语句进行初始化,因为在系统启动时,已自动对系统类进行初始化,分配了相应的内存区

2、System类被final修饰,不能实例化。类中的方法和属性都是静态的

3、方法

(1)static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length):从指定源数组中复制一个数组,指定起止位置。速度较快

(2)static void exit(int status):终止当前正在运行的Java虚拟机。非0的状态码表示异常终止

(3)static void gc():运行垃圾回收器。System.gc();  ==  Runtime.getRuntime().gc();

注:对象.finalize() = System.gc()。System.gc()调用垃圾回收器,垃圾回收器在运行的时候,才会调用finalize()方法

(4)static String getProperty(String key):获取用指定键描述的系统属性。下面是部分key值:

         user.dir:用户目录

         user.name:用户名

         os.name:当前操作系统的名字

         java.version:java版本号

         file.separator:文件分隔符

         path.separator:路径分隔符

(5)static Properties getProperties():确定当前的系统属性(所有系统属性)。Properties extends Hashtable,存储的都是String类型的键值对。Properties类没有泛型,因为它里面的键和值都是String类型,其方法会直接操作字符串

    public static void main(String[] args) {

        //获取系统的属性信息,并存储到Properties集合中
        Properties properties = System.getProperties();
        //Properties集合中存储的都是String类型的键值对
        Set<String> keySet = properties.stringPropertyNames();
        for (String name : keySet) {
            //get()方法是Properties从其父类Hashtable继承而来的
            //get():返回的是Object,需要强转
//            String value = (String) properties.get(name);
            //getProperty():返回值类型是String。建议使用Properties类自己的方法getProperty()
            String value = properties.getProperty(name);
            System.out.println(name + ":" + value);
        }

    }

(5)static String setProperty(String key, String value):设置指定键指示的系统属性(全局的),返回系统属性以前的值。经过用户程序修改的系统属性是暂时性的,如果系统重新启动,系统属性会恢复原始属性

(6)static void setProperties(Properties props):将系统属性设置为Properties参数

(7)static void load(String filename):从作为动态库的本地文件系统中以指定的文件名加载代码文件。文件名参数必须是完整的路径名。System.load(filename);  ==  Runtime.getRuntime().load(filename);

(8)static void loadLibrary(String libname):加载由libname参数指定的系统库。将库名映射到实际系统库的方法取决于系统。System.loadLibrary(name);  ==  Runtime.getRuntime().loadLibrary(name);

4、关于getProperty()方法

(1)不同的操作系统,键都是固定的,先根据键获取值,再对值进行使用,提高程序的移植性(无论哪个系统,JVM启动时都会先获取系统信息)

eg:根据键(line.separator)获取行分隔符

    //任何系统都能获取当前系统的回车符
    System.getProperty("line.separator")

(2)将从系统中获取的信息直接定义成常量,系统一启动就可以立即获取

二、java.lang.Runtime

1、每个java应用程序都有一个Runtime类实例,使应用程序能够与其运行的环境相连接。应用程序不能创建自己的Runtime类实例,但可以通过getRuntime()方法获取。一旦得到了当前Runtime对象的实例,就可以调用Runtime对象的方法去控制Java虚拟机的状态和行为

注:java应用程序运行的环境实际上就是JVM,java application通过Runtime对象和其运行环境(JVM)打交道

2、当applet与其他不被信任的代码调用任何Runtime类的方法时,常常会引起SecurityException异常

3、如果一个类没有提供构造函数,而这个类中又有非静态方法,那么这个类至少有一个方法是静态的,并返回本类对象 -- 单例。Runtime类使用了单例设计模式,保证了运行时的Java程序的对象唯一性

注:如果有两个方法能返回本类对象,就不是单例。因为返回的是不同的内部创建对象

4、方法

(1)static Runtime getRuntime():返回与当前java应用程序相关的运行时对象

(2)void gc():运行垃圾回收器。Runtime.getRuntime().gc();  ==  System.gc();

(3)void exit(int status):通过启动虚拟机的关闭序列,终止当前正在运行的Java虚拟机。此方法从不正常返回,可以将变量作为一个状态码,非零的状态码表示非正常终止。Runtime.getRuntime().exit(-1);  ==  System.exit(-1);

(4)void halt(int status) :强行终止目前正在运行的Java虚拟机。此方法从不正常返回,非零的状态码表示非正常终止

(5)int availableProcessors():向Java虚拟机返回可用处理器的数目

(6)long totalMemory():返回Java虚拟机中的内存总量。返回的值取决于主机环境

(7)long freeMemory():返回Java虚拟机中的空闲内存量。调用gc()方法可能导致freeMemory()返回值的增加

(8)long maxMemory():返回Java虚拟机试图使用的最大内存量。如果内存本身没有限制,则返回值Long.MAX_VALUE

(9)Process exec(String command) throws IOException:在单独的进程中执行指定的字符串命令

(10)Process exec(String[] cmdarray) throws IOException:在单独的进程中执行指定命令和变量

    public static void main(String[] args) throws IOException {

        Runtime runtime = Runtime.getRuntime();
        //exec():开启硬盘上的执行文件(指定路径下)
        //打开一个记事本文件,当前目录没有就到path下找。如果指定文件不存在,抛出IOException
        runtime.exec("notepad.exe");
        //绝对路径也可以,双反斜杠\\是防止\被转义
        runtime.exec("C:\\tencent\\QQ.exe");
        //运行记事本程序(notepad.exe),用这个程序打开指定路径下的xxx.java文件。程序和文件路径之间用空格隔开
        runtime.exec("notepad.exe E:\\xxx.java");

    }

(11)void load(String filename):加载作为动态库的指定文件名。文件名变量必须是一个完整的路径名。Runtime.getRuntime().load(filename);  ==  System.load(filename);

(12)void loadLibrary(String libname):加载具有指定库名的动态库。从以前获取库文件的本地文件系统中加载含有本机代码的文件。这一过程的细节取决于实现方法,可以以某种特定于系统的方式完成从库名到特定文件名的映射

(13)void runFinalization():运行挂起finalization的所有对象的终止方法。Runtime.getRuntime().runFinalization();  ==  System.runFinalization();

三、java.lang.Process

1、public abstract class Process:进程(本地进程)

注:Process是抽象类,不能直接被继承,所以没有子类。只有存在着应用程序,才能去创建进程。但可以获取进程

2、Process类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法

3、ProcessBuilder.start()和Runtime.exec()方法创建一个本机进程,并返回Process子类的一个实例,该实例可用来控制进程并获得相关信息

4、构造方法

(1)Process()

5、方法

(1)abstract void destroy():杀掉子进程。强制终止此Process对象表示的子进程

(2)abstract int exitValue():返回子进程的出口值。0表示正常终止

(3)abstract InputStream getErrorStream():获取子进程的错误流。错误流获得由该Process对象表示的进程的错误输出流传送的数据

(4)abstract InputStream getInputStream():获取子进程的输入流。输入流获得由该Process对象表示的进程的标准输出流

(5)abstract OutputStream getOutputStream():获取子进程的输出流。输出流被传送给由该Process对象表示的进程的标准输入流

(6)abstract int waitFor() throws InterruptedException:导致当前线程等待。如有必要,一直要等到由该Process对象表示的进程已经终止。如果已终止该子进程,此方法立即返回。如果没有终止该子进程,调用的线程将被阻塞,直到退出子进程。返回进程的出口值,0表示正常终止

    public static void main(String[] args) throws IOException, InterruptedException {

        /**
         * 功能:打开一个记事本,5秒后关闭
         */
        Runtime runtime = Runtime.getRuntime();
        //只有存在着应用程序,才能去创建进程
        Process process = runtime.exec("notepad.exe");
        Thread.sleep(5000);
        //只能杀掉runtime对象自己开启的进程
        process.destroy();

    }

四、垃圾收集(System.gc()、System.runFinalization()和Object的finalize())

1、System.gc():告诉垃圾收集器打算进行垃圾收集,而垃圾收集器进不进行收集是不确定的。占了内存但是没有利用,把没有被垃圾回收机制处理的对象尽可能的处理掉

2、System.runFinalization():强制调用已经失去引用的对象的finalize()方法。强制垃圾回收机制尽可能的回收没有被利用的对象,以释放出其占用的内存

        System.gc();
        //要在runFinalization()之前执行gc()
        System.runFinalization();

3、finalize():Object的方法。当垃圾收集器认为没有指向对象实例的引用时,会在销毁该对象之前调用finalize()方法。该方法最常见的作用是确保释放实例占用的全部资源。java并不保证定时为对象实例调用该方法,甚至不保证方法会被调用,所以该方法不应该用于正常内存处理

 

<think>好的,我现在需要解决用户关于Java中runFinalization方法以及如何调用挂起对象的finalize方法的问题。用户还提到不建议使用finalize,我需要结合这些点来组织回答。 首先,我应该回顾一下用户提供的引用内容。引用[1]提到,如果不显式调用runFinalization,JVM会在需要时自动执行终止过程。这说明runFinalization方法的作用可能与触发终止处理有关,可能涉及finalize方法的调用。用户的问题正是关于这个方法的作用以及如何调用挂起对象的finalize,所以引用[1]是关键。 接下来,用户引用了Runtime类相关的信息(引用[2]),说明Runtime是单例模式,应用程序通过getRuntime()获取实例。这可能与调用runFinalization方法的方式有关,因为Runtime类中可能有这个方法。 然后,用户还提到了destroy方法(引用[3])线程池策略(引用[4]),但这些可能当前问题关联不大,暂时可以忽略,除非需要对比资源回收策略。 现在,我需要明确runFinalization方法的作用。根据Java文档,System.runFinalization()Runtime.getRuntime().runFinalization()方法会建议JVM执行等待终结的对象的finalize方法。但实际调用时间由JVM决定,不能保证立即执行。这可能与引用[1]中的内容一致,即JVM自行管理,显式调用可能只是触发建议。 关于如何调用挂起对象的finalize方法,用户可能指的是那些已经被垃圾回收器标记为可回收,但尚未执行finalize的对象。不过,在Java中,finalize方法是由垃圾回收器在回收对象前调用的,而对象变为不可达后,才会被加入finalization队列,由Finalizer线程处理。所以显式调用runFinalization可能促使JVM尽快处理这些队列中的对象。 但用户提到“不建议使用finalize”,所以需要解释为什么,可能涉及finalize的缺点,比如执行不确定性、性能问题、可能导致内存泄漏等。同时,替代方案如Cleaner类或AutoCloseable接口。 接下来,我需要组织回答的结构: 1. 解释runFinalization方法的作用,引用[1]作为支持。 2. 说明如何调用该方法,通过SystemRuntime类,引用[2]提到Runtime的单例模式。 3. 讨论为何不建议使用finalize,以及替代方案。 4. 相关问题部分生成相关问题。 需要确保语言口语化,结构清晰,符合用户要求的中文回答,使用正确的LaTeX格式,如方法名用行内公式,如$System.runFinalization()$。 需要验证Java中runFinalization的具体行为,比如该方法是否会立即执行finalize,还是只是建议。根据Java文档,这个方法提示JVM尝试运行等待终结的对象的finalize方法,但无法保证。因此,用户不能依赖它来立即触发finalize。 此外,用户提到“调用处于挂起状态对象的finalize方法”,可能误解了对象状态。对象在进入finalization队列时,处于待终结状态,但无法直接调用其finalize方法,只能由JVM的Finalizer线程处理。即使显式调用runFinalization,也无法指定特定对象,只能促使处理队列中的所有对象。 所以,在回答中需要澄清这一点,即runFinalization不能针对特定对象,而是全局处理。同时,强调finalize方法的不确定性,以及为什么应当避免使用。 现在,将这些点整合成自然的中文段落,并添加相关问题。</think>### Java Runtime.runFinalizationfinalize方法解析 #### 1. **`runFinalization`方法的作用** `System.runFinalization()`或`Runtime.getRuntime().runFinalization()`的作用是**建议JVM立即执行处于“待终结”状态对象的`finalize`方法**[^1]。 当一个对象被垃圾回收器标记为不可达时,如果其类重写了`finalize`方法,则该对象会被加入**终结队列(Finalization Queue)**,由JVM的`Finalizer`线程异步调用其`finalize`方法。`runFinalization`的作用是主动触发这一过程,但**无法保证立即执行**,具体时机仍由JVM决定。 #### 2. **为何不建议使用`finalize`方法?** - **不确定性**:`finalize`的执行时间不可控,可能导致资源释放延迟。 - **性能问题**:`Finalizer`线程优先级低,可能引发内存泄漏(对象长期滞留终结队列)[^1]。 - **复杂性**:不规范的`finalize`实现可能抛出异常,导致对象终结失败。 #### 3. **替代方案** - **`AutoCloseable`接口**:通过`try-with-resources`确保资源释放,例如: ```java try (FileInputStream fis = new FileInputStream("file.txt")) { // 使用资源 } // 自动调用close() ``` - **`Cleaner`类(Java 9+)**:提供更安全的对象清理机制,替代`finalize`。 #### 4. **示例代码(仅演示逻辑,实际不推荐使用`finalize`)** ```java public class Example { @Override protected void finalize() throws Throwable { System.out.println("finalize被调用"); super.finalize(); } public static void main(String[] args) { Example obj = new Example(); obj = null; // 对象变为不可达 System.gc(); // 建议JVM执行GC System.runFinalization(); // 建议执行终结 } } ``` > **注意**:即使调用`System.runFinalization()`,`finalize`的输出仍可能因JVM优化而无法观测到。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值