浅谈java内存泄露

来源:互联网 发布:windows一键还原官网 编辑:程序博客网 时间:2024/05/17 23:54

java的垃圾回收机制是GC(Garbage Collection,垃圾收集,垃圾回收),是java和C/C++主要的区别。首先我们来了解一下jvm的的内存划分



1.每个程序计数器记录一个线程的行号,通过改变程序计数器的值来取下一条指令。

2.虚拟机栈,一个线程的每个方法在执行的同时,就会创建一个栈帧(Stack Frame),栈帧中存储的有局部变量表、操作站、动态链接、方法出口等,当方法被调用时,栈帧在JVM栈中入栈,当方法执行完成时,栈帧出栈。

虚拟机栈中定义了两种异常,如果线程调用的栈深度大于虚拟机允许的最大深度,则抛出StatckOverFlowError(栈溢出);不过多 数Java虚拟机都允许动态扩展虚拟机栈的大小(有少部分是固定长度的),所以线程可以一直申请栈,知道内存不足,此时,会抛出 OutOfMemoryError(内存溢出)。

3.本地方法栈:是用来执行NATIVE程序,就是C语言。

4 堆区(Heap):堆区是为了存储对象实例,所有的对象都在堆区上分配内存,如果内存不足就会抛出OutOfMemoryError:Java heap space异常。

5 方法区:方法区是各个线程共享的区域,用于存储已经被虚拟机加载的类信息(即加载类时需要加载的信息,包括版本、field、方法、接口等信息)、final常量、静态变量、编译器即时编译的代码等。有人把方法区叫做持久区,java8hi做些改变了。本来是将堆分为青年带,老年带、持久带。

年轻带分为一个新生代、s0、s1两复活带,
初级回收将年轻代分为三个区域,  一个新生代 , 2个大小相同的复活代,  应用程序只能使用一个新生代和一个复活代, 当发生初级垃圾回收的时候,gc挂起程序, 然后将新生代和复活代中的存活对象复制到另外一个非活动的复活代中,然后一次性清除新生代和复活代,将原来的非复活代标记成为活动复活代.    将在指定次数回收后仍然存在的对象移动到年老代中, 初级回收后,得到一个空的可用的新生代.。发生15次后,将任然存在的对象移动到老年代,初级回收得到的是一个空的可用的新生代。

堆设置 -Xms :初始堆大小 -Xmx :最大堆大小 -XX:NewSize=n :设置年轻代大小 -XX:NewRatio=n: 设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4 -XX:SurvivorRatio=n :年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5 -XX:MaxPermSize=n :设置持久代大小 收集器设置 -XX:+UseSerialGC :设置串行收集器 -XX:...

内存泄漏可能是程序错误,也可能是JVM参数配置问题

用代码谈内存泄漏

变量和引用存储在栈中,常量存储在常量池中。

String a=new String("123");//开辟一个内存空间

String b=new String("123");//开辟另一个内存空间

String c="123";//在常量池里面找有无“123”,有就直接引用,没有就在创建一个

String d="123";

System.ou.println(a==b);//2

Sysem.out.println(c==d);//2


这里解释一下黄色这3个箭头,对于通过new产生一个字符串(假设为”china”)时,会先去常量池中查找是否已经有了”china”对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此”china”对象的拷贝对象。这也就是有道面试题:String s = new String(“xyz”);产生几个对象?一个或两个,如果常量池中原来没有”xyz”,就是两个

原创粉丝点击