JAVA常用类--Runtime类
Runtime类
Runtime类描述的是一种运行时,在Java程序执行过程中,所有的java程序都一定要运行在JVM(虚拟机)的进程中
有了JVM进程,就需要一种类型可以描述当前进程的相关环境以及与之相关的处理操作,即Java设计出了Runtime类
每个JVM的进程中都会自动包含有一个Runtime类的实例化对象,打开Runtime类之后就可以看见相关文档
[查看文档链接](java.base (Java SE 11 & JDK 11 ) (oracle.com))
每一个JavaDos文档应该按照"成员"、"构造"、"方法"的形式进行类的结构展示,而Runtime类的文档直接给出的是"方法"摘要
原因:Runtime类中的构造方法被隐藏了,是私有属性的,因此可知Runtime类应该属于单例设计模式如下:
(注意:若属于多例设计模式,在新的开发版本中一定会使用枚举来描述)
private Runtime(){}
将Runtime类设置为单例设计模式,主要是因为每个JVM进程只需要提供一个Runtime类的实例化对象,所有和JVM有关的信息实际上都在Runtime类中提供了操作。图解如下:
虽然Runtime类是单例设计模式,但从本质上来讲单例设计模式都会在内部提供一个获取本类实例化对象的static方法,这个方法在Runtime类中也存在;Runtime类常用的处理方法如下:
方法名称 | 类型 | 描述 |
---|---|---|
public static Runtime getRuntime() | 普通 | 获取Runtime类的实例化对象 |
public static exec(String command) throws IOException | 普通 | 开启新的子进程 |
public long maxMemory() | 普通 | 最大可用内存 |
public long totalMemor() | 普通 | 可用内存 |
public long freeMemory() | 普通 | 空余内存 |
public void gc() | 普通 | 手工执行GC |
通过以上的方法列表可知,在Runtime类中可以直接通过exec()方法创建一个新的子进程,而如果想要对这个子进程进行控制,则可以依据Process类来完成!
实例1:通过Runtime类创建新进程
//Runtime类
public class Application {
public static void main(String[] args) throws Exception {
Runtime runtime = Runtime.getRuntime();//获取Runtime类的对象实例
//每当通过Runtime启动了一个进程之后实际上会返回一个进程对象
Process process = runtime.exec("notepad.exe");//打开Windows系统中的记事本
Thread.sleep(2000);//进程运行2秒
process.destroy();//销毁进程
}
}
实例2:观察内存数据
在以后实际的项目开发过程中,对于Runtime类来讲比较重要的操作就在于内存信息的动态获取,整个Java程序的正确执行都需要依靠内存的支持,如果内存不能保证正确运行环境,那么程序就会出现严重的性能问题!!
//Runtime类
public class Application {
//2.观察内存数据
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
System.out.println("【1】MaxMemory = "+ runtime.maxMemory());
System.out.println("【1】TotalMemory = "+ runtime.totalMemory());
System.out.println("【1】FreeMemory = "+ runtime.freeMemory());
}
}
运行结果如下:
【1】MaxMemory = 1875378176
【1】TotalMemory = 126877696
【1】FreeMemory = 124193056
注意:
-
MaxMemory默认是物理内存的四分之一,TotalMemory默认是物理内存的六十四分之一
如下图为本机的物理内存:
-
以上代码可以直接返回具体的内存大小数据,返回的内存大小单位是字节,在Java程序设计中,所有与文件大小有关的操作都会与long数据类型进行定义;
-
整个JVM(虚拟机)进程的可用最大内存(MaxMemory) > 默认的可用内存(TotalMemory,该值会发生改变,但最终不超过MaxMemory) > 空闲内存(FreeMemory)
-
如果空闲内存不足者TotalMemory也会进行动态的扩充(这种动态的扩充机制实际上是非常伤害程序的)
实例3:动态获取内存信息
public class Application {
//2.观察内存数据
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
System.out.println("【1】垃圾产生前的内存信息:MaxMemory = "+ runtime.maxMemory());
System.out.println("【1】垃圾产生前的内存信息:TotalMemory = "+ runtime.totalMemory());
System.out.println("【1】垃圾产生前的内存信息:FreeMemory = "+ runtime.freeMemory());
String message = "abcd";//定义字符串
for(int x = 0;x < 20;x++){
message +=message + x +"\n";//产生大量的垃圾
}
//runtime.gc();//手工进行垃圾清除
System.out.println("【2】垃圾产生后的内存信息:MaxMemory = "+ runtime.maxMemory());
System.out.println("【2】垃圾产生后的内存信息:TotalMemory = "+ runtime.totalMemory());
System.out.println("【2】垃圾产生后的内存信息:FreeMemory = "+ runtime.freeMemory());
}
}
运行结果如下:
【1】垃圾产生前的内存信息:MaxMemory = 1875378176
【1】垃圾产生前的内存信息:TotalMemory = 126877696 //注意变化
【1】垃圾产生前的内存信息:FreeMemory = 124193056 //注意变化
【2】垃圾产生后的内存信息:MaxMemory = 1875378176
【2】垃圾产生后的内存信息:TotalMemory = 160432128 //注意变化
【2】垃圾产生后的内存信息:FreeMemory = 94067232 //注意变化
通过当前程序执行可知,此时可以使用的堆内存空余空间已经有所减少,随着程序垃圾的产生一定会浪费大量的堆内存空间,这样就可以通过Runtime类动态的获取内存信息!
报错:
如果此时内存空间已经被垃圾空间严重占满了,并且来不及进行扩充,则会出现以下的报错信息,
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
- 这属于内存溢出的问题
- 这种OOM问题需要通过JVM调优来完成
实例4:gc()调用
如果清除程序可能会存在大量的垃圾,那么最佳做法就是进行垃圾清除,可以利用Runtime类中提供的gc()方法来完成此类操作!
当使用gc()进行垃圾清除之后可以发现空闲的空间已经被回收了,这样可以便于后续程序的高效咨执行
public class Application {
//2.观察内存数据
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
System.out.println("【1】垃圾产生前的内存信息:MaxMemory = "+ runtime.maxMemory());
System.out.println("【1】垃圾产生前的内存信息:TotalMemory = "+ runtime.totalMemory());
System.out.println("【1】垃圾产生前的内存信息:FreeMemory = "+ runtime.freeMemory());
String message = "abcd";//定义字符串
for(int x = 0;x < 20;x++){
message +=message + x +"\n";//产生大量的垃圾
}
runtime.gc();//手工进行垃圾清除
System.out.println("【2】GC调用后的内存信息:MaxMemory = "+ runtime.maxMemory());
System.out.println("【2】GC调用后的内存信息:TotalMemory = "+ runtime.totalMemory());
System.out.println("【2】GC调用后的内存信息:FreeMemory = "+ runtime.freeMemory());
}
}
运行结果如下:
【1】垃圾产生前的内存信息:MaxMemory = 1875378176
【1】垃圾产生前的内存信息:TotalMemory = 126877696 //注意变化
【1】垃圾产生前的内存信息:FreeMemory = 124193056 //注意变化
【2】GC调用后的内存信息:MaxMemory = 1875378176
【2】GC调用后的内存信息:TotalMemory = 160432128 //注意变化
【2】GC调用后的内存信息:FreeMemory = 145912272 //注意变化
总结:
Java之中的所有GC属于守护线程(守护线程是伴随主线程而存在的),主要目的是进行垃圾的收集以及堆内存空间释放
如果要进行gc的处理,在JVM(虚拟机)进程中有两种处理形式:
- 自动的垃圾收集(需要清除整个的JVM体系结构)
- 手工的垃圾收集(Runtime类中的gc()方法)