二,java内存区域和内存溢出
**2.2运行时数据区域(方法区/程序计数器/堆/虚拟机栈/本地方法栈)**
2.2.1程序计数器:存放当前线程执行的行号指示器,处理线程下一条需要执行的指令,分支,循环,跳转,异常处理等都需要用程序计数器来完成。该区域不会出现oom。
2.2.2虚拟机栈:线程私有的,每个方法的执行都创建一个栈帧来存局部变量表,操作树栈,动态链接,方法出口等,每个方法执行都对应着一个压栈和弹栈的操作。
2.2.3本地方法栈:java执行nactive方法。
2.2.4java堆:虚拟机中最大的内存区域,存放java对象,分为:新生代和老年代。新生代又包括:den区+2个survivor。
2.2.5方法区:也成为永久代,方法区包括常量池。存放类描述信息,常量,静态变量。
2.2.6直接内存:nio用的就是直接内存,通过java堆中的DirectByteBuffer来做对这块内存的引用。避免java堆和nactive堆数据的来回复制。
**2.3虚拟接对象探秘**
2.3.1对象的创建:在类加载过程中为类分配内存时,如果内存是规整的,有用的内存放一边,没用的放一边,就可以通过挪动指针来分配,称为:指针碰撞。如果是内存是不规则的话,就从虚拟机维护的一个可用内存列表中分配,称为:空闲列表。垃圾收集算法中:serial/panew/compact用的是指针碰撞,cms用的是空闲列表。
2.3.2对象内存布局:对象头,实例数据,对齐填充。
2.3.3对象访问定位:1.通过访问句柄池,找到对象对象数据和方法区。2.通过堆中指针访问对象数据和方法区。
**2.4oom异常**
2.4.1java堆溢出:通过限制最大堆大小,不断创建对象,并保持该对象被引用不被回收即可oom。
2.4.2虚拟机栈和本地方栈溢出:1.*,通过设置-Xss栈大小,不断递归调用方法既模拟栈溢出,2.不断创建线程就可以模拟outOfMemery。
2.4.3方法区溢出:常量池可以通过不断调用string.intern(),String.intern()会存在放常量池。方法区存放类的描述信息/静态变量等,可以限制pergen通过cglib不断生成对象。
2.4.4本地直接内存溢出
三,垃圾回收策略和内存分配策略
**3.3垃圾回收算法**
3.3.1标记-清除:标记和清除效率都不高,还会导致内存碎片
3.3.2复制算法:把还存活的复制到另一块内存,然后将旧的内存清空,这样就避免了内存碎片问题,但是会造成内存利用率只有一半,但是因为很多对象是很快就死掉了,所以新生代把eden+survivor默认设置为8:1.这样只有百分10的内存浪费。
3.3.3标记-整理:将存活的对象向一端移动,清除掉端末以外的内存。
3.3.4分代收集
**3.5垃圾收集器**
3.5.1serial收集器:使用一个线程收集,收集期间会暂停所以工作线程,stop the world。缺点:效率太低;优点:实现简单。所以默认的jdk-client模式的新生代回收策略用的是他。
3.5.2parnew收集器:多线程版的serail收集器。
3.5.3parallel收集器:复制收集器,并且也是多线程。跟parnew或者其他收集器不一样的地方是,其他收集器关注的是尽量缩短垃圾回收暂停时间。而parallel是达到一个可控制的吞吐量。吞吐量=运行用户时间/(运行用户时间+垃圾回收时间)。
3.5.4serial old收集器:serial老年代版本。
3.5.5parallel old收集器:parallel收集器老年代版本。
3.5.6cms收集器:初始标记-并发标记-重新标记-并发清楚。优点:只有初始标记和重复会stop the world,但是标记时间很短。其他都是可以和用户执行的线程一起并行执行。所以效率高。缺点:冰法标记和清除的时候gc线程和用户线程交替执行,占用cpu资源。并且该收集器是基于标记-清除算法,会造成内存碎片。
3.5.7g1收集器。并行并发,分代收集,空间整合(标记-整理)
3.5.8理解gc日志:[GC和[Full GC,full gc表示发生了stop the world。111k->0k(1024k)=回收前使用内存->回收后使用内存(该内存区域总量)
**3.6内存分配和回收策略**
3.6.1对象优先存放在eden区。
七,虚拟机类加载机制
**7.2类加载时机**:1,遇到new/getstatic/putstatic;2,反射reflet;3,初始化子类的时候父类被初始化;4,main函数;
**7.3类加载过程**:加载-验证-准备-解析-初始化-使用-卸载。
7.3.1加载:1.从zip,jar,war等;2.网络中获取;3.反射动态代理;4.jsp生成;5.数据库生成等
7.3.2验证:确保class字节流满足虚拟机要求
7.3.3准备:为类变量分配内存和赋初始值,在方法区分配内存。static被赋初始值。final的常量直接赋值在常量池中。
7.3.4解析:将符号引用替换未直接引用的过程。
7.3.5初始化:执行构造器cinit。
**7.4类加载器**
7.4.1类加载器:启动类加载器;拓展类加载器;应用程序类加载器;