内存管理往往是很多应用程序的关键部分,像在C/C++这些需要手动管理内存的语言中编程,稍有缺陷就有可能导致大量内存泄漏,从而使程序崩溃。Java提供了一个自动回收内存的垃圾收集器,让Java程序员能从内存管理中解脱出来,但是也存在缺点,那就是不能完全控制它什么时候执行什么时候不执行。
垃圾回收器,通常就叫它GC,GC实际上是一个受JVM控制的程序,它的核心任务就是删除Java程序运行不再触及的任何对象。所谓的“触及”是指Java程序中任何一个活动的线程存在对这个对象的引用。
GC是什么时候运行呢?
GC受JVM的控制,JVM决定什么时候运行GC,我们平常可以在程序中请求JVM进行垃圾回收,从而释放更多的内存供程序使用,但是在任何情况下,请求都无法保证JVM会答应我们的请求,当我们请求回收时,短期内JVM会进行垃圾回收,但这没有任何保障。JVM会在它觉得必要的时候进行回收,如下面第一段和第二段代码,虽然第二段代码执行次数更多,但GC觉得内存不够了,它进行了回收,到最后占用的内存反而比第一段的代码占用的内存少。第三段代码我们可以看得到我们请求GC时还我内存的效果。System.gc(),看源码可以知道,实际上它调用了Runtime 的gc()方法。
public static void main(String[] args) {
Runtime rt = Runtime.getRuntime();
System.out.println("Total JVM memory:" + rt.totalMemory());
System.out.println("Before Memory=" + rt.freeMemory());
Date d = null;
for(int i=0;i<100000;i++){
d = new Date();
d = null;
}
System.out.println("After Memory=" + rt.freeMemory());
rt.gc();
System.out.println("After GC Memory=" + rt.freeMemory() );
System.out.println("=======================");
System.out.println("Before Memory=" + rt.freeMemory());
for(int i=0;i<10000000;i++){
d = new Date();
d = null;
}
System.out.println("After Memory=" + rt.freeMemory());
rt.gc();
System.out.println("After GC Memory=" + rt.freeMemory() );
System.out.println("=======================");
System.out.println("Before Memory=" + rt.freeMemory());
Date[] ds2 = new Date[1000000];
for(int i=0;i<1000000;i++){
ds2[i] = new Date();
}
System.out.println("After Memory=" + rt.freeMemory());
rt.gc();
System.out.println("After GC Memory=" + rt.freeMemory() );
}
执行结果:
Total JVM memory:5177344
Before Memory=4945624
After Memory=4254216
After GC Memory=5024744
=======================
Before Memory=5024744
After Memory=4197480
After GC Memory=5020280
=======================
Before Memory=5020280
After Memory=18211424
After GC Memory=46200736
请求GC的时候,JVM往往并不会马上响应我们的要求,finalize()方法是每一个对象回收时都会运行一次的方法,并且仅一次,一般不要重写finalize()方法,在此方法中可以让该需要回收的对象起死回生,让它重新被引用,从而让该对象免于被回收,但是此方法只执行一次,当下次该对象符合回收条件的时候,JVM会判断已经执行过finalize()了,将不再执行了。运行如下代码,你会发现请求并不那么有效,被回收的对象也不是那么有先后顺序了。
public class FinalizeTest {
int num;
public FinalizeTest(int num){
this.num = num;
}
/**
* @author ZhangXiang
* @param args
* 2010-1-15
*/
public static void main(String[] args) {
FinalizeTest ft = null;
for(int i=0;i<100000;i++){
ft = new FinalizeTest(i);
ft = null;
System.gc();
}
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("FinalizeTest"+this.num);
}
}
GC是怎么样工作的呢?
首先我们得要了解垃圾回收的条件,前面也提到:当没有任何活的线程能够访问一个对象时,该对象就符合垃圾回收的条件了,有一个例外,String存在于String常量池中,虽然它也是对象,但我们感觉它更像常量一样,表现更反复无常。虽然我们没办法完全控制GC工作,但是我们还是能适当指引它运行,为其回收对我们没用的对象创造条件:
1、空引用
很简单,只需要把引用我们不需要的对象的变量设置为Null,如下面的代码
Date date = new Date();
Sytem.out.println(date);
date = null;
2、为变量重新赋值
就是给引用垃圾对象的变量重新赋一个值,如下面的代码第一次new得到的象在变量被赋予一个新对象的时候就已经符合回收的条件了,当然等待它的也就是回收的命运了
Date date = new Date();
Sytem.out.println(date);
date = new Date();
3、隔离引用
当对象中的属性对其它对象进行交叉引用,如果两个对象都存在彼此的引用,即使其它对这两个对象的引用都被删除,但是这两个对象都还存在一个有效引用,这样不会符合回收条件,要让GC能够回收它们就需要打破这样的一个环,如果是多个对象也许就是拆散一个网,隔离出来不再需要的对象,从而让它满足被回收的条件,如以下代码,当到doSth()时i3就已经满足被回收的条件了。
public class Island {
Island i;
Island ii;
/**
* @author ZhangXiang
* @param args
* 2010-1-15
*/
public static void main(String[] args) {
Island i1 = new Island();
Island i2 = new Island();
Island i3 = new Island();
i1.i = i2;//i1引用i2
i2.i = i3;//i2引用i3
i3.i = i1;//i3引用i1
i1.ii = i3;//i1又引用i3
i2.ii = i1;//i2又引用i1
i3.ii = i2;//i3引用i2
//隔离出i3,使它满足被回收的条件
i2.i= null;
i1.ii = null;
//doSth();
}
}
java GC虽然是自动执行的,但是了解它的原理,知道它是怎么执行的,有时候在实际开发中对我们的帮助还是蛮大的,这也是平常找工作面试、笔试常考的知识点,学习了好多次,总是隔段时间就要忘记不少,记下来分享下,也起到提醒自己的作用吧,当是笔记咯。
一般都只是看看别人写的博,自己很少写,有时看看自己写的文章,发现差距还是很大,其实写博也是记录自己成长的一种方式吧,学习中,还请大家多多指教。
分享到:
相关推荐
自动垃圾收集是Java内存管理的一个重要特性,它自动地回收不再使用的对象占用的内存空间,从而避免了手动管理内存带来的内存泄漏等问题。Java的垃圾收集器定期检查不再引用的对象,并释放它们占用的内存。这一机制极...
JVM性能调优涉及到内存分配、垃圾回收机制调优等。 性能监控工具可以帮助开发者监测JVM运行时的状态,分析性能瓶颈。 文件中还提及了Java架构师在学习Java时应当关注的高级主题,例如机器学习和数据库设计。机器...
内存管理和垃圾回收是Java的另一大特点。读者会了解到Java虚拟机(JVM)如何自动管理内存,以及对象生命周期的概念,这有助于优化程序性能和防止内存泄漏。 并发编程是现代软件开发中的重要一环。Java提供了丰富的...
9. **垃圾回收与内存管理**:Java的自动内存管理是其一大优势,书中会介绍如何理解和优化垃圾回收机制。 10. **标准库**:Java标准库提供了大量实用类和接口,如Collections、Arrays、Date和Time等,熟悉并善用它们...
堆空间是由Java虚拟机(JVM)管理的,通过垃圾回收机制来释放不再使用的对象所占用的空间。堆内存相较于栈内存来说更为庞大,但也因此导致访问速度相对较慢。 **2. 栈与堆的访问速度** 由于栈空间是由操作系统直接...
Java中的垃圾回收器负责回收堆中的内存,垃圾回收器会自动回收不再使用的对象的内存,而C语言中堆是由程序员手动释放的。 该资源主要讨论了C语言指针和Java引用的概念、实现、差异和应用场景,旨在帮助读者更好地...
在学习这两本书的过程中,你会了解到Java的垃圾回收机制,它是Java平台的一大特色,可以自动管理内存,避免内存泄漏。同时,你还会接触到Java标准库,其中包含大量实用类和接口,如Collections框架,用于处理数组和...
5. **深入理解**:通过解决这些谜题,读者可以深化对Java内存模型、垃圾回收机制、对象生命周期等复杂概念的理解。 6. **代码分析**:每个谜题后都有详细的解答,分析了代码为什么会得到预期之外的结果,并解释了...
11. **JVM内存模型**:解释Java虚拟机的工作原理,包括堆内存、栈内存、方法区、本地方法栈等区域,以及垃圾回收机制。 12. **设计模式**:介绍常见的设计模式,如单例、工厂、观察者、装饰者等,并探讨它们在实际...
1. Java 语言的内存回收:Java 语言具有自动垃圾回收机制,内存回收程序负责释放无用内存。 2. Java 语言的内存管理方式:Java 语言使用堆栈式内存管理方式,程序员不需要手动释放内存。 三、Java 语言的开发工具 ...
- **自动内存管理**:Java通过垃圾回收机制自动管理内存,避免了内存泄露的问题。 - **安全**:Java有内置的安全机制,防止恶意代码的执行。 - **健壮性**:Java有严格的类型检查和异常处理机制,提高了程序的...
- 健壮性和安全性:强类型、异常处理、自动垃圾回收等特性增强程序稳定性与安全性。 6. **字节码** - 字节码是Java源代码编译后的中间表示,不依赖特定硬件,仅针对虚拟机。 - 采用字节码的优点:提高了执行效率...
其中,Java因其自动内存垃圾回收机制而成为现代编程语言中的热门选择。根据TIOBE指数,2008年4月时,Java的流行度位居第一,占有20.5%的市场份额,表明其在业界的广泛应用。 编程语言的流行度不仅反映在市场份额上...
3. **垃圾回收机制**:Java自动管理内存,程序员无需手动释放内存,降低了内存泄漏的风险。 4. **异常处理**:Java通过try-catch-finally语句块进行异常处理,增强了程序的健壮性。 5. **多线程**:Java内置了对多...
以及对异常处理、内存管理(垃圾回收机制)的理解。此外,掌握Java集合框架,如List、Set、Map接口及其实现类的使用,是Java面试中的常考点。 其次,深入理解JVM(Java虚拟机)是Java开发者的重要技能。JVM的工作...
同时,书中还涵盖了异常处理、垃圾回收机制、集合框架、线程同步等重要主题,这些都是Java程序员日常工作中不可或缺的知识。 在程序设计方面,书中强调了代码的可读性、可维护性和高效性。作者介绍了如何编写整洁、...
1. **Java开发**:Java是一种简单且面向对象的语言,它与C/C++语法相似,但去除了如多继承、操作符重载等复杂特性,同时具备自动垃圾回收机制,减轻了内存管理的负担。Java的核心概念包括类、接口和继承,这些都是...
3. **自动内存管理**:Java引入了垃圾回收机制(Garbage Collection),自动管理内存,避免了内存泄漏的问题,简化了程序员的工作。 4. **安全性**:Java具有严格的类型检查和安全管理机制,可以防止恶意代码对系统...
9. **垃圾回收与内存管理**:Java的自动内存管理是其一大特点,书中会解释垃圾回收的工作原理和内存分配策略。 10. **接口与抽象类**:接口和抽象类是Java中的两种抽象方式,书中将解释它们的使用场景和区别。 11....