找工作——JVM内存管理

Posted cjt1991

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了找工作——JVM内存管理相关的知识,希望对你有一定的参考价值。

1. JVM类加载机制

类从被加载到虚拟机内存开始,到卸载出内存为止,它的整个生命周期包括:加载、连接(验证、准备、解析)、初始化、使用和卸载阶段。

加载:根据查找路径找到对应的class文件,然后倒入。

   检查:检查待加载的class文件的正确性。

 准备:给类中的静态变量分配存储空间。

   解析:将符号引用转化成直接引用。

初始化:对静态变量和静态代码执行初始化工作。

Java字节代码的表现形式是字节数组(byte[]),而Java类在JVM中的表现形式是java.lang.Class类的对象。一个Java类从字节代码到能够在JVM中被使用,需要经过加载、链接和初始化这三个步骤。这三个步骤中,对开发人员直接可见的是Java类的加载,通过使用Java类加载器(class loader)可以在运行时刻动态的加载一个Java类;而链接和初始化则是在使用Java类之前会发生的动作。

原理:类加载器本身一个类,其实质是把类文件从硬盘读取到内存中。在Java语言中类的加载时动态的,它并不会一次性将所有类全部加载后再运行,而是保证程序运行的基础类完全加载到JVM中国,至于其它类,则在需要时才加载。在Java语言中,可以把类分为3类:系统类、扩展类和自定义类。Java针对这3种不同类提供了3中类型的加载器

启动类加载器:Bootstrap ClassLoader,它负责加载系统类(lib\rt.jar的类),扩展类加载器:Extension ClassLoader,它负责加载扩展类(jre\lib\ext\*.jar的类),应用程序类加载器:Application ClassLoader,它负责加载用户类路径(ClassPath)所指定的类。以上3类加载器是通过委托方式来完成类的加载,具体而言就是当有类需要被载入的时,类加载器会请求父类来完成这个工作,父类会使用其自己的搜索路径来搜索需要被载入的类,如果搜索不到,才会由子类按照其搜索路径来搜索待加载的类。

2. JVM运行时数据区(JVM内存分配情况)

Java虚拟机定义了若干种程序运行时使用到的运行时数据区

   有些是随虚拟机的启动而创建,随虚拟机的退出而销毁。

   第二种则是与线程对应,随着线程的开始和结束而创建和销毁。

技术分享

程序计数器:字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础都需要依赖这个计数器来完成。如果线程正在执行的是一个java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Native方法,这个计数器值为空。此内存区域是唯一一个在Java虚拟机没有规定任何OutOfMemoryError情况的区域。

虚拟机栈:此栈中的元素叫做栈帧,线程在调用Java方法时,会为每一个方法创建一个栈帧,来存储局部变量表、操作栈、动态链接、方法出口等信息。每个方法被调用和完成的过程,都对应一个栈帧从虚拟机上入栈和出栈的过程。虚拟机栈的生命周期和线程相同。

本地方法栈:为线程私有,功能和虚拟机栈非常类似。来存储线程调用本地方法时,本地方法的局部变量表、操作栈等信息。

:堆(Heap)区被所有线程共享,在虚拟机启动时创建。此区的功能就是存放对象实例,几乎所有的对象实例都是在这里分配内容。Heap区是垃圾回收器管理的主要区域。

     现在的的垃圾收集器都采用分代收集算法,所以Java堆还可以细分为新生代和老年代,进一步划分的目的是为了更好回收内存。

方法区:该区为各个线程共享,用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译出来的代码等数据。

3. 垃圾回收算法

   在垃圾收集钱需要判断对象是否存活:引用计数法、可达性分析算法

   Java堆中各代分布:

   heap区又分:Eden Space(伊甸园)、Survivor Space(幸存者区)、Tenured Gen(老年代-养老区)、Perm Gen(永久代)(注:许多人多喜欢把方法区成为“永久代”,本质上两者并不等价,只因为HotSpot虚拟机的设计团队把GC分代收集扩展至方法区,这样可以像管理Java堆一样管理这部分内存,能够省去专门为方法区编写内存管理代码的工作,对于其他虚拟机来说不存在永久代的概念)

   Young:主要是用来存放新生的对象。

 Old:主要存放应用程序中生命周期长的内存对象。

 Permanent:是指内存的永久保存区域,主要存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域. 它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。

http://my.oschina.net/sunnywu/blog/332870

2. JVM 使用的GC算法是什么?

分代收集。

即将内存分为几个区域,将不同生命周期的对象放在不同区域里;

在GC收集的时候,频繁收集生命周期短的区域(Young area);

比较少的收集生命周期比较长的区域(Old area);

基本不收集的永久区(Perm area)。

3. GC 和 Full GC 有什么区别?

GC(或Minor GC):收集 生命周期短的区域(Young area)。

Full GC (或Major GC):收集生命周期短的区域(Young area)和生命周期比较长的区域(Old area)对整个堆进行垃圾收集。

他们的收集算法不同,所以使用的时间也不同。 GC 效率也会比较高,我们要尽量减少 Full GC 的次数。 当显示调用System.gc() 时,gc does a full collection(both young generation and tenured generation).

   标记—清除算法:

 复制算法:

 标记—清理算法:

 分代收集算法:

 

引用:强引用、软应用、弱引用、虚引用

   老年代,新生代、持久代

以上是关于找工作——JVM内存管理的主要内容,如果未能解决你的问题,请参考以下文章

内存管理

Spark原理 内存管理

Java内存模型和JVM内存管理

详解JVM内存管理与垃圾回收机制 (上)

JVM谈谈JVM内存区域的划分

JVM内存管理:深入Java内存区域与OOM