JVM
-
Java程序执行流程
-
JVM调优即调整堆(方法区属于特殊的堆)
类加载器
作用:加载Class文件
从底层开始加载器层级递进
- 虚拟键自带加载器
- 启动类(根)加载器
- 拓展类加载器
- 应用程序加载器
双亲委派机制
编写的类先由应用程序加载器加载,双亲委派机制即先向上找拓展类加载器,看拓展类加载器中有无同包同名的类,无则继续向上找根加载器,看根加载器有无同包同名的类进行加载,有则执行,没有则抛出异常返回应用程序加载器中加载当前类
沙箱安全机制
Java安全模型的核心就是Java沙箱(sandbox),沙箱是一个限制程序运行的环境,沙箱机制就是将Java代码限定在虚拟机(JVM)t特定的运行范围中,并且严格限制代码对本地系统资源访问,来保证对代码的有效隔离,防止对本地系统造成破坏,限制系统资源访问是沙箱的主要目的,系统资源包括:CPU、内存、文件系统、网络。
最新的安全机制实现,引入了域Domain的概念,虚拟机会将所有代码加载到不同的系统域和应用域,系统域部分专门负责与关键资源交互,应用域部分则通过系统域的代理来对所需资源进行访问,虚拟机中不同的受保护域对应不一样的权限
沙箱基本组件
-
字节码校验器
:确保Java类文件符合Java语言规范,帮助Java程序实现内存保护 -
类装载器
:采用双亲委派机制-
防止恶意代码干涉可信代码
-
守护被信任的类库边界
-
将代码归入保护域,确定了代码可以进行哪些操作
-
Native
native关键字修饰的方法说明Java的方法无法达到,会去调用底层C语言的库
native修饰的方法调用会进入本地方法栈中,再调用本地方法接口JNI实现,
Java Native Interface:JNI,拓展Java的使用,融合不同的编程语言为Java所用
在本地方法栈中登记native方法,最终执行时通过JNI加载本地方法库中的方法
方法区
线程安全,被所有线程共享的,包含方法字节码,静态变量,如构造函数、接口代码也在此定义,即所有定义的方法的信息都保存在该区域,静态变量赋值的常量在其中划分单独区域常量池进行保存,但实例变量存在堆内存中与方法区无关
方法区存放内容:存放class二进制文件。包含类信息、静态变量,常量池(String字符串和final修饰的常量值等),类的版本号等基本信息。
栈
先进后出,后进先出,
程序正在执行的方法一定在栈的顶部;
程序先调main方法进栈,在main方法中调用其他方法进栈,方法执行完毕后出栈,直到其他方法全部执行完毕后,全部出栈,main方法才出栈程序运行完毕,主线程结束,栈内存同步释放,即栈的生命周期与线程同步
栈存放内容:为即时调用的方法开辟空间,存储局部变量值(基本数据类型),局部变量引用,局部变量必须手动初始化
堆:Heap
一个Jvm只有一个堆内存,堆内存大小可调节。
堆内存划分:
-
新生区:
新生区可细分为三个区,伊甸园区(Eden)和2个幸存者区(Survivor),新创建的对象被分配在伊甸园区,2个幸存者区轮流扮演From与To的角色,保证To区为空;当伊甸园区无剩余空间存放对象时,触发执行针对新生代的垃圾回收minorGC,在轻GC后伊甸园区中存活的对象复制到"To",扮演"From"的幸存者区中存活的对象依据其经历的轻GC的次数决定去向,达到一定阈值的存活对象被移动到老年区,未达到的对象被复制到"To"区域,此时伊甸园区与From区中对象被清空,当执行下一次轻GC时,From与To的角色互换
-
老年区
-
永久区
常驻内存区域,存放JDK自身携带的Class对象、Interface元数据;存储Java运行时的环境或类信息,本区域不存在垃圾回收,随虚拟机的关闭而释放内存
- JDK1.8去永久代后,无永久代,常量池存在于元空间,原空间仅逻辑地址与新生代老年代相邻,物理地址不相邻
堆存放内容:存放引用类型的对象,即new出来的对象、数组值、类的非静态成员变量值(基本数据类型)、非静态成员变量引用。其中非静态成员变量在实例化时开辟空间初始化值。更具体点,非静态成员变量近似于放在堆的对象中。
-
堆内存调优
默认情况下,堆的最大分配内存是总内存的1/4,初始化的内存为1/64
当程序出现OOM异常,可使用参数
-XX:+HeapDumpOnOutOfMemoryError
,抓取内存快照,通过Jprofiler分析内存快照排错
垃圾回收
GC的作用区域仅限于堆
- 常用算法
- 复制算法:主要作用新生代的伊甸园区与两个幸存者区,负责将from区的对象复制到To区,原From区清空准备下一次扮演To区
- 优点:没有内存碎片
- 缺点:有内存区域一直未使用
- 标记清除算法:首先扫描标记出所有需要回收的对象,在标记完成后再次扫描统一回收所有被标记的对象
- 优点:不需要额外的空间
- 缺点:两次扫描影响效率,会产生内存碎片
- 标记压缩算法:在标记清除算法的基础上,再次扫描,使所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
- 优点:不会产生空间碎片
- 缺点:效率再次降低
- 总结:
- 内存效率:复制算法>标记清除算法>标记压缩算法
- 内存整齐度:复制算犯=标记压缩算法>标记清除算法
- 内存利用率:标记压缩算法>标记清除算法>复制算法
- 常用方式:
- 新生代:存活率低
- 复制算法
- 老年区:区域大,存活率高
- 标记清除+标记压缩混合实现
- 新生代:存活率低
- 复制算法:主要作用新生代的伊甸园区与两个幸存者区,负责将from区的对象复制到To区,原From区清空准备下一次扮演To区
JMM
Java内存模型
- 作用:缓存一致性协议,用于定义数据读写的规则
- JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存中存储了该线程以读/写共享变量的副本
- 即主内存存放共享变量,每个线程都有一个私有的本地工作内存,存放从主内存中拷贝的数据,并对其进行操作
- 由此带来了共享对象的可见性的问题,即线程中副本变量的更改对其余线程不可见
线程都有一个私有的本地内存,本地内存中存储了该线程以读/写共享变量的副本
- 即主内存存放共享变量,每个线程都有一个私有的本地工作内存,存放从主内存中拷贝的数据,并对其进行操作
- 由此带来了共享对象的可见性的问题,即线程中副本变量的更改对其余线程不可见