1 开头:
jvm作为java中一个非常重要的组成部分,最近复习了相关的知识,现在将自己的理解总结如下:
jvm大致包括几个方面1:代码执行 2 内存管理 3 线程管理
代码执行:主要负责java字节码的执行,java作为跨平台语言的基础则是jvm,java字节码在不同的平台上有不同的jvm进行执行,达到java代码不用关心平台的效果。在这里jvm主要负责字节码的执行等操作。
内存管理:C代码需要显示的进行内存回收等操作,而java是有jvm来自动执行。包括垃圾回收机制,垃圾回收器,分代回收算法等内容。
线程管理:jvm还承担起线程的控制
1.1 java类加载机制
1.1.1流程
要知道生成的java字节码是如何执行的,需要了解java的类机制。
jvm的类加载机制分为:加载,验证,准备,解析,初始化
**加载**:在内存中生成一个代表这个类的java.lang.Class对 象,作为方法区这个类的各种数据的入口。
**验证**:验证class文件是否符合规范
**准备**:准备内存空间,在方法区中分配这些变量所使 用的内存空间
**解析**:虚拟机将常量池中的符号引用替换为直接引用的过程,
**初始化**:真正的开始执行java代码,执行类构造器<client>方法的过程。<client>方法是由编译器自动收集类中的类变 量的赋值操作和静态语句块中的语句合并而成的
这里解释一下符号引用和直接引用:在Java中,一个java类将会编译成一个class文件。在编译时,java类并不知道所引用的类的实际地址,因此只能使用符号引用来代替 各种虚拟机实现的内存布局可能有所不同,但是它们能接受的符号引用都是一致的。而直接引用是加载到内存中的,符号引用需要转化中内存中的直接引用才能真正的找到类。
1.1.2 类加载器
加载阶段是由类加载器进行执行的,负责动态加载Java类到Java虚拟机的内存空间中。
根类加载器:它用来加载 Java 的核心类,是用原生代码来实现的,并不继承自 java.lang.ClassLoader
扩展类加载器:它负责加载JRE的扩展目录,lib/ext或者由java.ext.dirs系统属性指定的目录中的JAR包的类。由Java语言实现,父类加载器为null
系统类加载器:被称为系统(也称为应用)类加载器,它负责在JVM启动时加载来自Java命令的-classpath选项、java.class.path系统属性,或者CLASSPATH换将变量所指定的JAR包和类路径
类加载器加载Class大致要经过如下8个步骤:
1.检测此Class是否载入过,即在缓冲区中是否有此Class,如果有直接进入第8步,否则进入第2步。
2.如果没有父类加载器,则要么Parent是根类加载器,要么本身就是根类加载器,则跳到第4步,如果父类加载器存在,则进入第3步。
3.请求使用父类加载器去载入目标类,如果载入成功则跳至第8步,否则接着执行第5步。
4.请求使用根类加载器去载入目标类,如果载入成功则跳至第8步,否则跳至第7步。
5.当前类加载器尝试寻找Class文件,如果找到则执行第6步,如果找不到则执行第7步。
6.从文件中载入Class,成功后跳至第8步。
7.抛出ClassNotFountException异常。
8.返回对应的java.lang.Class对象。
JVM的类加载机制
•全盘负责:全程由该加载器负责
•双亲委派:先交给父类加载器,只有父类不行才交给子类,好处是避免类的重复加载
•缓存机制:类加载器先从缓存区中搜寻该Class,只有当缓存区中不存在该Class对象时,系统才会读取该类对应的二进制数据
1.2 java内存管理
网上讲解内存管理的文章特别多,篇幅也很长,这里只对其中基本,重要的知识做一个总结。
内存管理:内存区域划分,垃圾回收机制,垃圾回收算法(分代收集),垃圾回收器,jvm参数配置
1.2.1 内存区域
方法区:存放类信息,常量,静态变量
堆:对象 线程共享
本地方法栈:c代码,本地方法
程序计数器: 程序执行的指令(指向虚拟机字节码指令的位置) ,线程私有 唯一没有内存移除的地方。
虚拟机栈: 存储栈帧,每个方法会创建一个栈帧 线程私有的
1.2.2 内存回收
在这里请看以下几个问题。
1)什么对象会被垃圾回收?
2)gc要做的是什么事情
3)垃圾回收有哪些算法
现在一一回答以上问题。
1 什么对象会被回收
jvm在初始化的时候,会生成一个根节点。我们采用的是根节点引用法,也就是一个对象如果从根节点开始,找不到对其的连接则判定该对象是需要被回收的对象。
2 gc要做的事情
标记需要被回收的对象,怎么回收 ,什么时候回收
3 垃圾回收算法
常见的有:标记删除,标记复制,标记整理
分代收集:分代收集将内存分为新生代和老年代。而新生代又分为eden,suriviveform survive to,三个区域。在新生代中采用的标记复制算法。对象在eden和suriviveform和survive to进行转换,对象每经历一次monitorgc,年龄加一,当年龄加到16移动到老年代。当老年代也不足时候,除非fullgc
jdk1.8以后 永久代改为元数据区。理论上只受到系统内存大小限制。该区域存储了class的一些信息,包括运行时常量池、Classloader的引用,字段数据,方法数据 、
4 垃圾回收器 这里主要说cms和g1 cms:多线程执行,基于标记清楚,以获取最短的垃圾回收停顿时间为目的 ,缺点是会产生内存碎片 g1:多线程执行,分域收集,可控制优先清理内存占据较大的区域,避免内存碎片,可控制停顿时间,基于标记整理
5 jvm参数配置
在这里列举一些会常常用到的参数配置
-Xms :初始堆大小
-Xmx :最大堆
-Xmn :年轻代
-Xss :每个线程大小