第七章 java堆

 

 java堆

一.内存溢出的原因

     

    1.堆溢出

        当堆中强引用对象占用了大部分空间,导致内存无法回收,对象大小之和大于-Xmx就会导致堆溢出.

    2.直接内存溢出

        下面的代码申请直接内存,导致直接内存溢出 . 当JAVA进程的所有内存之和(堆空间,栈空间,直接内存,以及虚拟机自身所用的内存)大于-Xmx *2的时候,就会出现OOM.

         

-Xmx1g -XX:+PrintGCDetails  (32位虚拟机,用户空间为2GB)  	 
for(int i = 0 ;i< 1024;i++){ 
            ByteBuffer b = ByteBuffer.allocateDirect(1024*1024);
  } 

      3.过多线程导致OOM

 

       

-Xmx1g -XX:+PrintGCDetails  
public static class OOMThread implements Runnable{
    public void run(){
       Thread.sleep(10000000);
    }
}  	 

public static void main(String[] args) {

  for(int i = 0 ;i< 100000;i++){ 
          new Thread(new OOMThread()).start();
  } 
}

       有两种方法可以解决

      1.减小堆空间大小 -Xmx. 2.减小每个线程所占用的线程空间  -Xss

 

    4.永久去溢出

      -XX:PermSize,然后不断的产生新类,用cglib

 

    5.GC效率地下导致OOM

         1.GC的时间超过98%.

         2.老年代释放内存小于2%

         3.eden区释放的内存小于2%

         4.连续5次出现上诉条件.就会抛出 GC overhead limit exceeded

 

 

二. String 在虚拟机中的实现

 

       1.不变性

          一旦生成一个String对象,就不能进行改变.主要作用于多线程访问时, 省略同步的时间,提高性能.String的一些看起来是修改的操作,实质上都是通过新建字符串对象来实现的.

       2.针对常量池的优化

         当两个字符串拥有相同的值时,它们指向常量池的同一个拷贝.这样可以大量节省内存空间.

         

                String str1 = new String("abc");
		String str2 = new String("abc");
		System.out.println(str1.intern() == str2.intern());//true

       

 

 

       3.String常量池的位置

 

        在虚拟机中,有一块称为常量池的区间专门用于存放字符串常量.jdk1.6之前,这块区域属于永久区,jdk1.7之后被移动到堆中进行管理.

        String.intern()方法返回常量池中的字符串,如果不存在就放入常量池.

        下面的程序可以看出jdk1.6是在永久区,1.7之后是在堆中

 

jdk1.8:-Xmx5m -XX:MaxMetaspaceSize=5m -XX:-UseGCOverheadLimit
jdk1.6:-Xmx5m -XX:MaxPermSize=5m 
jdk1.7:-Xmx5m -XX:MaxPermSize=5m
public static void main(String[] args) {
		List<String> test  = new ArrayList<String>();
		for(int i = 0 ;i< 100000;i++){
			test.add(String.valueOf(i).intern());
		}
	}

        

 

 

 三.使用MAT分析java堆

       

      打开eclipse中的Memory Analysis试图,用菜单File ->Acquire Heap Dump  选择要分析的堆.生成分析数据

     

 

     这个试图里面可以观察到堆快照里类大小,类,实例,所有类的内存使用情况,线程以及线程内局部变量的信息.

     

 

 


  

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值