Runtime类
在每一个JVM进程中,都会存在一个运行时的操作类的对象,而这个对象所属的类型就是Runtime类。利用Runtime类可以启动新的进程或进行相关运行时环境的操作。例如:取得内存空间以及释放垃圾空间。(Runtime类是一个典型的单利设计模式)。
Runtime类的常用方法:
方法 | 类型 | 描述 |
---|---|---|
public static Runtime getRuntime() | 普通 | 取得Runtime类实例化对象 |
public long maxMemory() | 普通 | 返回最大可用内存大小 |
public long totalMemory() | 普通 | 返回所有可用内存大小 |
public long freeMemory() | 普通 | 返回所有空余内存大小 |
public void gc() | 普通 | 执行垃圾回收操作 |
public Process exec(String command ) throws IOException | 普通 | 创建新的进程 |
注意:在Runtime类有一个非常重要的方法:public void gc() ,用于运行垃圾收集器,释放垃圾空间,即调用此方法后产生的垃圾空间将被释放。上述返回的内存大小均以字节为单位。
例如:
import org.junit.Test;
public class TestDemo {
@Test
public void test(){
Runtime runtime = Runtime.getRuntime();
long maxMemory = runtime.maxMemory();//返回为字节单位
long totalMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
System.out.println("Max:"+maxMemory);
System.out.println("total:" + totalMemory);
System.out.println("free:" + freeMemory);
}
}
执行结果:
Max:1883242496
total:128974848
free:120075264
java的内存空间是可以调整的。
每一个块内存空间都会存在一个内存伸缩区,当内存空间不足时就会动态开辟。所以为了提高性能,在实际应用中可能会开辟尽量大一些的内存空间,可以使用如下参数:
- “-Xms”:初始分配内存,默认大小为1/64物理内存大小,但是小于1G
- “-Xmx”: 最大分配内存,默认大小为1/4物理内存大小,但是小于1G
- “-Xmn”: 设置年轻代堆内存大小。
一般都会将"-Xms"和"-Xmx"两个参数的数值设置为相同,以减少申请内存空间的时间。
垃圾释放实例:
@Test
public void gcTest(){
Runtime runtime = Runtime.getRuntime();
//产生垃圾
String string = "";
for (int i = 0;i<2000;i++){
string+=i;
}
System.out.println("垃圾处理前:Max="+runtime.maxMemory());
System.out.println("垃圾处理前:total="+runtime.totalMemory());
System.out.println("垃圾处理前:free="+runtime.freeMemory());
//释放空间
runtime.gc();
System.out.println("垃圾处理后:Max="+runtime.maxMemory());
System.out.println("垃圾处理后:total="+runtime.totalMemory());
System.out.println("垃圾处理后:free="+runtime.freeMemory());
}
执行结果:
垃圾处理前:Max=1883242496
垃圾处理前:total=128974848
垃圾处理前:free=101445928
垃圾处理后:Max=1883242496
垃圾处理后:total=128974848
垃圾处理后:free=127240608
垃圾回收处理与对象创建
虽然垃圾收集只通过一个gc() 方法就可以实现,但是垃圾回收与java 的内存划分也是有关系的。因为垃圾回收主要对年轻代与旧生代的内存进行回收。
年轻代内存空间用于释放新产生的对象,而经过若干次回收还没有被回收掉的对象向旧生代内存空间移动。对年轻代进行垃圾回收称为MinorGcC(从垃圾收集),对旧生代垃圾回收称为MajorGC(主垃圾收集),并且两块内存回收互不干涉。在JVM中的对象回收机制会使用分代回收(Generational Collection)的策略,用较高的频率对年轻代对象进行扫描和回收,而对旧生代对象则用较低的频率进行回收,这样就不需要在每次执行GC 时将内存中的所有对象都检查一遍。
对于GC 的执行可以用文字描述为:当JVM 剩余内存空间不足时会触发GC,如果Eden 内存空间不足就要进行从回收,旧生代空间不足时要进行主回收,永久代空间不足时会进行完全垃圾收集(Full GC)。
(1)当使用关键字 new 创建一个新对象时,JVM 会将新对象保存在Eden 区,但是此时需要判断Eden 区是否空余空间,如果有,则直接将新对象保存在Eden 区,如果没有,则执行年轻代回收。
(2)在执行完年轻代回收后会清除掉不活跃的对象,从而释放Eden 区的内存空间,随后会对Eden 空间进行再次判断。如果此时剩余空间可以直接容纳新对象,则会直接为新对象申请内存空间;如果此时Eden 区的空间依然不足,则会将部分活跃对象保存在Survivor区。
(3)由于Survivor 区也有对象会存储在内,所以保存Eden 区发送来的对象前首先判断其空间是否充足,如果Survivor 有足够的空余空间,则直接保存Eden 去晋升来的对象,那么此时Eden 区将得到空间释放,随后可以在Eden 区为新的对象申请内存空间的开辟;如果Survivor 空间不足,就需要将Survivor 区部分活跃对象保存在Tenured 区。
(4)Tenured 区如果有足够的内存空间,则将Survivor 区发送来的对象进行保存,如果此时Tenured 区的内存空间也已经满了,则将执行“Full GC”,以释放年老代中保存的不活跃对象,从而Survivor 将保存Eden 发送来的对象,这样就可以在Eden 区内有足够的内存保存新的对象。
(5)如果此时老年代的内存区也已经被占满,则会抛出 “OutOfMemoryError”,程序将中断运行。
其他功能
实际上Runtime 有一个更加有意思的功能,它可以调用本机的可执行程序,并且创建进程, 例如调用 Windows的画板。
@Test
public void testRun() throws IOException, InterruptedException {
Runtime runtime = Runtime.getRuntime();
Process exec = runtime.exec("mspaint.exe");
Thread.sleep(2000);// 2s后关闭
exec.destroy();
}