一、JVM的位置
二、JVM的体系结构
三、类加载器
作用 : 加载class文件
四、什么是双亲委派机制?
双亲委派机制的工作过程:就是双亲委派机制的原理
- 1、类加载器收到类加载的请求
- 2、把这个请求委托给 父加载器去完成,一直向上委托,直到启动类加载器(根)
- 3、启动类加载器检查能不能加载( 使用findClass()方法 ),就能加载(结束),否则抛出异常,通知子加载器进行加载
- 4、重复步骤三
五、沙箱安全机制
Java安全模型的核心就是Java沙箱(sandbox),沙箱是一个限制程序运行的环境。沙箱机制就是将Java代码限定在虚拟机 特定的运行范围中,并且严格限制代码对本地系统资源访问,通过这样的措施来保证对代码的有效隔离,防止对本地系统进行破坏,沙箱主要限制系统资源访问。
组成沙箱的基本组件:
-
字节码校验器(bytecode verifier):确保Java类文件遵循Java语言规范,这样可以帮助Java程序实习内存保护,但并不是所有的类文件都会经过字节码校验,比如核心类(java包下,javax包下…)就比如我们刚开始入门Java的时候,在记事本写错了 编译的时候(javac) 会直接报错。
-
类装载器(class loader):其中类加载器在3个方面对Java沙箱起作用
· 它防止恶意代码去干涉善意的代码 (双亲委派机制)
· 它守护了被信任的类库边界 (双亲委派机制)
· 它将代码归入保护域,确定了代码可以进行哪些操作。(沙箱安全机制)虚拟机为不同的类加载器载入的类 提供不同的命名空间,命名空间由一系列唯一的名称组成,每一个被装载的类将有一个名字,这个命名空间是由Java虚拟机为每个类装载器维护的,它们互相之间甚至不可见、
类加载器采用的是双亲委派模式。
1、从最内层 JVM 自带类加载器开始加载,外层恶意同名类得不到加载从而无法使用。
2、由于严格通过包来区分了访问域,外层恶意的类通过内置代码也无法获得权限访问到内层类,破坏代码就自然无法生效。 -
存取控制器(access controller):
存取控制器可以控制核心 API 对操作系统的存取权限,而这个控制的策略设定,可以由用户指定。 -
安全管理器(security manager):
是核心 API 和操作系统之间的主要接口,实现权限控制,比存取控制器优先级高。 -
安全软件包(security package):
Java.security 下的类和扩展包下的类,允许用户为自己的应用增加新的安全特性,包括:
安全提供者、消息摘要、数字签名、加密、鉴别
六、Native
凡是带了 native 关键字的,说明 Java的作用范围达不到了,会去调用底层C语言的库!,声名为native的方法 执行时,它会在内存区中专门开辟了一块标记区域:Native Method Stack 并登记 native 方法,在最终执行时,调用本地方法本地接口 JNI,在( Execution Engine )执行引擎执行的时候加载 Native Libraries( 本地库 )
JNI :Java Native Interface (Java本地方法接口)
凡是带了native关键字的方法就会进入本地方法栈,其他的就是Java栈
它的作用:扩展Java的使用,融合不同的编程语言为Java所用
比如 多线程中的 start0() 方法,就是去调用C语言。
或者Java程序驱动打印机等,才需要 声名为native方法
七、PC寄存器
程序计数器:Program Counter Register
每一个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向 类似一条指令的地址,也就是即将要执行的指令代码),它是一个非常小的内存空间,几乎可以忽略不计。
八、方法区 Method Area 方法区
方法区是所用线程共享的一块区域,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法的信息都保存在该区域,此区域属于共享区间;
静态变量、常量、类信息(构造方法、接口定义)、运行时的常量池存在方法区中,但是 实例变量存在堆内存中,和方法区无关。
九、栈
先进后出、后进先出
所以说 main方法先执行,但是最后结束
栈:栈内存,主管程序的运行,生命周期和线程同步
线程结束,栈内存也释放,对栈来说,不存在垃圾回收问题
一旦线程结束,栈就结束
栈一般存放:八大基本类型、对象引用、实例方法
栈运行原理:栈帧
栈溢出:StackOverflowError
十、三种JVM
JVM查看 CMD -> java -version
- Sun公司 HotSpot
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
(我们学习的JVM) - BEA
JRockit
- IBM
J9 VM
十一、堆
Heap,一个JVM 只有一个堆内存,堆内存的大小是可以调节的。
类加载器读取了类文件后,一般会把 类、方法、常量、变量、所有引用类型的真实对象 存放进堆中
堆内存细分为三个区域:
- 新生区(伊甸园区)Young / New
- 养老区 Old
- 永久区 Perm
GC垃圾回收,主要是在新生区和养老区(如果要细分的话具体是 新生区中的伊甸园区)
假设内存满了,OOM,堆内存不够,java.lang.OutOfMemoryError:java heap space
在 JDK8 之后,永久存储区改名成 元空间
十二、新生区、老年区
新生区:
- 类:诞生 和 成长 的地方,甚至死亡
- 伊甸园,所有的对象都是在 伊甸园区new出来的
- 幸存者区 (0,1)
老年区:
- 90%的对象都是临时对象
十三、永久区
这个区域常驻内存的。用来存放JDK自身携带的Class对象,Interface元数据,存储的是Java运行时的一些环境或类信息,这个区域不存在垃圾回收,关闭虚拟机就会释放这个区域的内存
一个启动类,加载了大量的第三方jar包,tomcat部署了太多的应用,大量动态生成的反射类,不断的被加载,直到内存满,就会出现OOM
- JDK1.6 之前: 永久代,常量池在方法区
- JDK1.7:永久代,但是在慢慢退化,
去永久代
,常量池在堆中 - JDK1.8:无永久代,常量池在元空间
元空间:逻辑上存在 物理上不存在
十四、GC 垃圾回收机制
JVM 在进行 GC 时,并不是对这三个区域统一回收,大部分时候,回收都是新生代
- 新生代
- 老年区
- 永久区
GC 两种类:轻GC(普通GC),重GC(全局GC)
GC题目:
- JVM 的内存模型和分区 详细到每个区放什么
-
堆里面的分区有哪些, Eden,from,to,老年区,说说它们的特点
-
GC的算法有哪些?标记清除法,标记压缩,复制算法,引用计数器,如何使用
内存效率:复制算法 > 标记清除算法 > 标记压缩算法
内存整齐度:复制算法 = 标记压缩算法 > 标记清除算法
内存利用率:标记压缩算法 = 标记清除算法 > 复制算法 -
有无最优算法?
没有最好的算法,只有最合适的算法 :分代收集算法
新生代:存活率低 适合 复制算法
老年代:考虑区域大,存活率问题 调整 标记清除(内存碎片不是太多)+标记压缩混合 实现 -
轻GC 和 重GC 分别是在什么时候发生的?