JVM学习笔记

来源:互联网 发布:美国的消防员知乎 编辑:程序博客网 时间:2024/06/05 02:45
本篇主要以面试为主

JVM可以划分为三部分

1 内存的分配和模型
2 GC
3 类的加载机制


一、运行时数据区


(转载自http://blog.csdn.net/zd836614437/article/details/64126826)

虚拟机栈(方法栈): 描述Java方法的内存模型,每当执行一个方法,会创建一个栈帧,存放了局部变量表(存放了基本数据类型,对象的引用,returnaddress类型),操作数栈,动态链接,和方法出口,方法的执行和结束对应一个栈帧入栈和出栈的过程,异常有StackOverflowError 和 OutOfMemoryError

本地方法栈:和虚拟机栈功能类似,不一样的是该栈提供对native方法的服务,即native修饰的代码块或方法(非java编写)

堆:Java 对象的主要存放区(启动时创建的一块最大内存区域),经常进行垃圾回收,所有线程共享

方法区:存放了类信息,常量,静态信息,有一个运行时常量池,用于存放静态变量

程序计数器:一小块内存区域,改变计数器的值可以选取下一条字节码指令


(转载自http://blog.csdn.net/zd836614437/article/details/64126826)

内存模型的理解
Java线程之间的通信,由Java内存模型(JMM)控制
每个线程在操作主内存的同时,自己本身维护了一个本地内存,里面存储了主内存变量的副本,当一个线程更改了本地内存的变量
后,会将最新的变量值刷新到主内存,其他变量在从主内存中读取最新的结果

二、GC(垃圾回收)
1 对象是否存活:引用计数器法(长时间未引用为0,引用一次对象+1),可达性分析算法(一系列GCRoots对象开始搜索的引用链,不存在则死亡)

【GCRoots对象:虚拟机栈引用的对象,方法区常量引用对象,方法区的静态引用对象,本地方法引用的对象】
2 垃圾回收算法:标记-清除 (统一标记,统一清除,存在效率和空间问题)
                标记-整理(将内存中的对象统一移至一端,清理掉端外的内存)
                复制算法 (将内存划分为两块,当其中一块内存不足时,将还存活的对象复制到另一块 eg:Eden Survivor)
                分代收集  (根据对象生命周期划分,年轻代:复制算法 老年代:标记-清除,标记-整理 )
                
3 常用垃圾收集器:单线程 eg:Serial收集器 工作时必须暂停其他所有线程,直到收集结束
                   多线程 eg:PaNew收集器 和Serial收集器基本一致 多线程
                  CMS :标记清除算法实现 过程:初始标记 并发标记 重新标记 并发清除
                  G1:面向服务的收集器,分代收集算法实现 过程:初始标记 并发标记 最终标记 筛选回收
                  【并发:多条垃圾收集线程并发执行,用户线程等待 并行:多条垃圾收集线程与用户线程交替执行(cpu分配)】

4 内存分配和回收的策略:优先在Eden区分配;大对象直接进入老年代;长期存活的对象进入老年代
5 总结垃圾回收过程:当虚拟机空闲或堆内存不足时,垃圾回收线程(低优先级)会进入堆中扫描长期未引用的对象,将他们加入回收集合,统一进行回收


三、类的加载机制
    类加载过程:1 编译:.java源代码编译成.class文件
                2 加载:.class文件被类加载器加载,通过反射创建字节码对象
                3 连接:验证(是否符合Java规范) 准备(为静态变量分配内存和初始值) 解析(符号引用替换为直接引用)
                4 初始化:执行类中的程序
            
    四种类加载器:启动类加载器:加载Java核心类
              扩展类加载器: 加载Java扩展类
              应用类加载器:加载类路径下的jar包
              自定义类加载器
    
    双亲委派模型:当一个加载器加载一个类时,首先要请求父加载器是否能加载,直到顶层(启动类加载器)。当父加载器无法加载时,才由子加载器加载
    缓存:每一层加载器都存在一个缓存,当确定该类加载器加载时,首先看缓存是否有该对象,如果存在则直接从缓存中读取,没有在由类加载器读取
    全权委托:当一个类加载器加载一个类时,也会加载该类引用的其他类

              

    
原创粉丝点击