public class FinalizeEscapeGC{
public static FinalizeEscapeGC instance=null;
public void isAlive(){
System.out.println("yes,i am still alive");
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("finalize methode execute");
instance = this; //把this赋给引用变量进行自救
}
public static void main(String [] args) throws InterruptedException {
instance=new FinalizeEscapeGC();
instance=null;
System.gc(); //调用System.gc()后,建议JVM进行一次Full GC
Thread.sleep(1000);
instance.isAlive();
//在没有重写finalize方法时,肯定是会报NullpointerException的
instance=null;
System.gc();
Thread.sleep(1000);
instance.isAlive();
}
}
结果
finalize method executed
yes,i am still alive
Exception in thread "main" java.lang.NullPointerException
at com.alioo.gc.FinalizeEscapeGC.main(FinalizeEscapeGC.java:29)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
现在的商业虚拟机都采用复制算法来回收新生代。但是并不是将新生代划分为大小相等的两块,而是分为一块较大的 Eden 空间和两块较小的 Survivor 空间(From Survivor 和 To Survivor,From Survivor的内存被分配,To Survivor为空),比例为8 : 1 : 1,每次使用 Eden 空间和From Survivor。在回收时,会对 Eden 和 From Survivor 中的对象进行回收,Eden中的存活对象被复制到 To Survivor,From Survivor中的存活对象如果达到了晋升年龄,则进入老年代,否则也被复制到 To Survivor,接下来清空 Eden 和 From Survivor ,将 From Survivor 和To Survivor 的身份互换,结束。 因为HotSpot 虚拟机的 Eden 和 Survivor 的大小比例默认为 8:1,保证了内存的利用率达到 90%,只需要浪费10%的内存空间即可实现带有压缩功能的垃圾收集方法,避免了内存碎片的问题。 如果每次回收有多于 10% 的对象存活,那么一块 Survivor 空间就不够用了,此时需要依赖于老年代进行分配担保,也就是借用老年代的空间存储放不下的对象。
什么是分配担保?
当JVM准备为一个对象分配内存空间时,发现此时Eden中空闲的区域无法装下该对象,那么就会触发Minor GC,对Eden + From Survivor的废弃对象进行回收,并把存活对象复制到To Survivor区。但如果Minor GC过后只有少量对象被回收,To Survivor无法装下存活对象,那么此时需要将Eden + From Survior中的所有对象都转移到老年代中,然后再将新对象存入Eden区。这个过程就是“分配担保”。
Minor GC:发生在新生代上,因为新生代对象存活时间很短,因此 Minor GC 会频繁执行,执行的速度一般也会比较快。
具体过程:Minor GC时,会对 Eden 和 From Survivor 中的对象进行回收,Eden中的存活对象被复制到 To Survivor,From Survivor中的存活对象如果达到了晋升年龄,则进入老年代,否则也被复制到 To Survivor,接下来清空 Eden 和 From Survivor ,将 From Survivor 和To Survivor 的身份互换,结束。 特别要注意!永远不会直接在Survivor上分配内存!对象优先被分配到Eden,当Eden空间不足时会触发Minor GC,然后将存活对象复制到Survivor区,即Survivor区的空间只能作为复制的目的地,而不是直接分配的目的地。
在发生 Minor GC 之前,虚拟机先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果条件成立的话,那么 Minor GC 可以确认是安全的。 如果不成立的话虚拟机会查看 HandlePromotionFailure 设置值是否允许担保失败,如果允许那么就会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试着进行一次 Minor GC;如果小于,或者 HandlePromotionFailure 设置不允许冒险,那么就要进行一次 Full GC。
通过引入 Region 的概念,从而将原来的一整块内存空间划分成多个的小空间,使得每个小空间可以单独进行垃圾回收。这种划分方法带来了很大的灵活性,使得可预测的停顿时间模型成为可能。通过记录每个 Region 垃圾回收时间以及回收所获得的空间(这两个值是通过过去回收的经验获得),并维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的 Region。
每个 Region 都有一个 Remembered Set,用来记录该 Region 对象的引用对象所在的 Region。通过使用 Remembered Set,在做可达性分析的时候就可以避免全堆扫描。
如果不计算维护 Remembered Set 的操作,G1 收集器的运作大致可划分为以下几个步骤:
初始标记
并发标记
最终标记:为了修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录,虚拟机将这段时间对象变化记录在线程的 Remembered Set Logs 里面,最终标记阶段需要把 Remembered Set Logs 的数据合并到 Remembered Set 中。这阶段需要停顿线程,但是可并行执行。
筛选回收:首先对各个 Region 中的回收价值和成本进行排序,根据用户所期望的 GC 停顿时间来制定回收计划。此阶段其实也可以做到与用户程序一起并发执行,但是因为只回收一部分 Region,时间是用户可控制的,而且停顿用户线程将大幅度提高收集效率。
具备如下特点:
空间整合:整体来看是基于“标记 - 整理”算法实现的收集器,从局部(两个 Region 之间)上来看是基于“复制”算法实现的,这意味着运行期间不会产生内存空间碎片。
可预测的停顿:能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在 GC 上的时间不得超过 N 毫秒。
public static void main(String[] args){
Set set = new HashSet();
Person p1 = new Person("唐僧","pwd1",25);
Person p2 = new Person("孙悟空","pwd2",26);
Person p3 = new Person("猪八戒","pwd3",27);
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:3 个元素!
p3.setAge(2); //修改p3的年龄,此时p3元素对应的hashcode值发生改变
set.remove(p3); //此时remove不掉,造成内存泄漏
set.add(p3); //重新添加,居然添加成功
System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:4 个元素!
for (Person person : set){
System.out.println(person);
}
}
1、java.lang.IllegalStateException: Class invariant violation
at org.apache.log4j.LogManager.getLoggerRepository(LogManager.java:199)at org.apache.log4j.LogManager.getLogger(LogManager.java:228)
at o
hadoop jps出现process information unavailable提示解决办法
jps时出现如下信息:
3019 -- process information unavailable3053 -- process information unavailable2985 -- process information unavailable2917 --
<?php
class Image{
private $path;
function __construct($path='./'){
$this->path=rtrim($path,'/').'/';
}
//水印函数,参数:背景图,水印图,位置,前缀,TMD透明度
public function water($b,$l,$pos