问题:操作系统底层对应的都是机器码010101
不同的操作系统底层对应的机器码、指令是不同的
JVM来解决这个问题 从软件层面屏蔽了底层硬件指令层面的细节
在下载的时候就将操作系统进行了分类 linux与java
整个的java知识体系就是JDK
JRE叫做java运行时环境 (jdbc lang util等等)
JVM 分类:
1.Java Hotspot Client VM
2.Java Hotspot Sever Vm
3.Selaris linux Windows other
JDK与JRE之间的差别
JDK比JRE多了Tools&Tool APIS
Tools&Tool APIS是java自带的工具 java javac javadoc等等
源码文件到.class文件 是JDK编译时环境
java的跨平台:JVM跨平台 属于JRE运行时环境
c与c++的跨平台是在编译时环境进行的跨平台 分操作系统的类库
源码文件 生产字节码文件.class 存储在本地计算机硬盘中
java HelloWorld.class 执行字节码文件
类加载子系统将.class加载到JVM运行时数据区
JVM运行时数据区在我们计算机的内存中
执行引擎去执行它 也就是CPU分配时间调度去执行它
即类加载子系统--JVM运行时数据区--执行引擎
其中 堆与方法区属于线程共享数据
栈 本地方法栈 程序计数器器 属于线程私有数据
处理高并发的项目的时候 并发问题 :就是当用户在同一时间访问同一共享数据区域 得到的结果会与理想结果存在差异 例如:100个线程执行i++ 结果有可能不是100
代码 由main线程执行
main线程里包含了栈 本地方法栈 程序计数器这三块线程私有数据
每个线程有它独立的栈 本地方法栈 程序计数器空间
public int add(){
int d=100;
return 100;
}
public static void main(String[] args){
Onject o=new Object();
o.add;
}
执行过程:
局部变量表
操作数栈
方法出口
附加信息
...
javap命令可以对字节码文件进行反汇编
字节码文件运行在JVM虚拟机 虚拟机依赖于操作系统 操作系统底层是机器码 JVM在这个过程中充当了 字节码与机器码之间的转换角色
iconst-1 将int数据1 压入操作数栈
istore-1 将局部变量a存入局部变量表 并且 操作数栈中的1赋值给a
即局部变量表存储着a=1;
iconst-2 将int数据2 压入操作数栈
istore-2 将局部变量b存入局部变量表 并且 操作数栈中的2赋值给b
即局部变量表存储着b=2;
操作数栈也是栈 先进后出 所以 2在1的上面
7为什么直接到9
7其实包含两个指令
7 bipush8位带符号整数压入栈
8 8位带符号整数对应100
也就是将100 压入操作数栈
imul 执行int类型的乘法 100*3=300 100 与3消失 300存入操作数栈
istore-3 将操作数栈中的int类型 存入局部变量表中的变量c
iload-3 将局部变量表中的c的值加载进来 将300加载到操作数栈
app存储在JVM运行时数据区的堆中 通过main栈帧的局部变量表中的app指向堆中的app
Sleep()被native修饰的方法 java没有实现 调用底层的c与其他实现
垃圾调优
性能调优
假设600m内存
堆中老年代占比三分之二 400m
堆中新生代占比三分之一 200m
新生代中Eden占比 五分之四 160m
新生代中from占比十分之一 20m
新生代中to占比十分之一 20m
新生代 老年代
Eden 包含from to
98%的对象在新生代的Eden伊甸园区创建
当创建的对象占满了堆内存中新生代的Eden时 会触发java的垃圾回收机制 minor gc
对当前创建的所有对象都进行判定
判定方式为:是否被其他地方所调用
如果two对象被调用 将他传入from区 并增加age=1;
这时 如果之前的one对象还是处于被调用的状态 那么他的age变为2 age=2;
并且 将one与two对象拷贝到to区
to区变为from区 froom区变为to区
当Eden区的对象又满了的时候 再次触发minor gc 进行gc root 根的可达性判定 判定方式同上
如果three对象被调用 将他传入from区 并增加age=1;
这时 如果之前的one对象还是处于被调用的状态 那么他的age变为3 age=3;
如果two对象不被调用了 two对象被移除
然后 将one与three对象拷贝到to区
to区变为from区 froom区变为to区
…
当minor gc进行15次之后 即one的age=15的时候
JVM会认为one对象是“老不死的对象”
此时one对象会进行晋升 晋升到老年代
假如from内存为40m 当from区中的对象占比20m时 这20m对象都会晋升 成为老年代
触发full gc会出现 STW现象(停顿现象)
JVM分配内存在进行压缩的时候 会占用一些资源 导致程序会出现不能响应的问题 即STW
STW Stop-The-World
是在执行垃圾收集算法时,Java应用程序的其他所有线程都被挂起(除了垃圾收集帮助器之外)。Java中一种全局暂停现象,全局停顿,所有Java代码停止,native代码可以执行,但不能与JVM交互;这些现象多半是由于gc引起
例如 双十一 不能出现停顿
当我们创建的对象越来越多的时候 堆所使用的内存越来越多 JVM分配的内存也会越来越大
当JVM分配的内存达到临界值的时候 会进行JVM分配内存的压缩 进行性能调优 也就是垃圾回收
进行性能调优的原因 :
对象在新生代存活15次 尽量在新生代就被回收
实在不行 再晋升老年代
JAVA采用分代回收思想的原因: