导致OutOfMemoryError异常的常见原因:
1内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
2集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
3代码中存在死循环或循环产生过多重复的对象实体;
4使用的第三方软件中的BUG;
5启动参数内存值设定的过小;
根本上解决Java内存溢出的唯一方法就是修改程序,及时地释放没用的对象,释放内存空间
Runtime.freeMemory() 方法返回剩余空间的字节数,Runtime.totalMemory() 方法总内存的字节数,Runtime.maxMemory() 返回最大内存的字节数。
>>新生代:复制清理; 老年代:标记-清除和标记-压缩算法; 永久代:存放Java中的类和加载类的类加载器本身。
运行时数据区分为:
运行时数据区通常包括这几个部分:
线程私有:
1程序计数器(Program Counter Register)、
2虚拟机栈(VM Stack)、
用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
3本地方法栈(Native Method Stack)、
线程共享:
4方法区(Method Area)(永久代)
它存储了每个类的结构信息,例如运行时常量池、字段、方法数据、构造函数和普通方法的字节码内容,还包括一些在类、实例、接口初始化时用到的特殊方法。
-XX:PermSize 设置最小空间
-XX:MaxPermSize 设置最大空间
Metaspace:
-XX:MetaspaceSize/-XX:MaxMetaspaceSize/
-XX:MinMetaspaceFreeRatio/-XX:MaxMetaspaceFreeRatio
5堆(Heap)(存放对象实例/数组)。[关键字new出来的对象]
新生代/老年代/[-Xms/-Xmx/-Xmn:设置新生代的内存大小]
[
堆和栈的区别
1 缓存来看
堆则是存放在二级缓存中
栈使用的是一级缓存
2 数据结构来看
堆(数据结构):堆可以被看成是一棵树,如:堆排序。
栈(数据结构):一种先进后出的数据结构。
3 空间分配
堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表
栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
4 更新速度
.堆内存的更新速度没有栈内存快因为局部变量的生命周期很短
5 堆是栈的一个组成元素
]
核心:
JVM类加载机制主要包括两个问题:类加载的时机与步骤 和 类加载的方式。
定义:
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型的过程就是虚拟机的 类加载机制
加载机制
装载-连接(验证-准备-解析)-初始化-使用-卸载
实现方式:
Java类加载的方式:类加载器、双亲委派机制
常用搜索算法:
根搜索算法
常用回收算法:
1 引用计数法/
2标记—清除算法/
3标记—压缩清除算法(java中老年代)/
4复制算法(java新生代)/
5分代收集(java堆)/
6分区算法/
常用的垃圾回收器有以下四种:
1.串行回收器
2.并行/吞吐量回收器
3.CMS回收器
[初始标记->并发标记->重新标记->并发清除]
4.G1回收器
内存回收
收集器:引用计数收集器、跟踪收集器
Jvm参数
-Xmx|最大堆内存/-Xms初始堆内存/-Xss|每个线程的栈内存/-Xmn|设置年轻代/
-XX:NewSize|年轻代初始值/-XX:MaxNewSize|年轻代最大值/-XX:PermSize|持久代初始值/-XX:MaxPermSize|持久代最大值/-XX:NewRatio|年轻代与老年代的比值/
减少gc次数
对象不用时最好显示为null/
尽量避免少使用system.gc()/
尽量少使用静态变量/
尽量使用stringbuffer而不是使用string/
分散对象创建或删除的时间/
尽量少用fianliza函数/
图片-软引用/
增加-Xmx的值/
能使用基本数据类型就不要使用对象
[
强:不会轻易回收
软:内存够,不回收;内存不够,回收
弱:随时会被回收
虚:任何时候都可能会被回收
]
触发类加载器的时机
创建类的实例,(new)/访问类的静态变量/访问类的静态方法/反射/初始化一个类的子类/虚拟机启动时,定义了main方法的那个类
Jvm提供的类加载器
调优:
Sun JDK监控和故障处理命令有jps jstat jmap jhat jstack jinfo;
常用调优工具分为两类,
jdk自带监控工具:jconsole和jvisualvm,
第三方有:MAT(Memory Analyzer Tool)、GChisto