1.JVM启动流程
2.JVM基本结构
2.1PC寄存器
-每个线程拥有一个PC寄存器
-在线程创建时,创建
-指向下一条指令的地址
-执行本地方法时,PC的值为undefined
2.2方法区
-保存装载的类信息
-----类型的常量池
-----字段,方法信息
-----方法字节码
-通常和永久区Perm关联在一起
-----永久区用于保存相对稳定的数据
2.3 Java堆
-和程序开发密切相关
-应用系统对象都保存在java堆中
-所有现场共享堆
-对分代GC来说,堆也是分代的
-GC的主要工作区间
新生代,生存区,老年代
2.4Java栈
-线程私有
-栈有一系列帧组成(因此java栈也叫作帧栈)
-帧保存一个方法的局部变量、操作数栈、常量池指针
-每一次方法调用创建一个帧,并压栈
静态和非静态的区别是,第一个是不是this引用
每次方法调用产生一个帧,故递归开始前的帧在最底部,然后层数越多,栈顶越高,最后可能出现栈溢出
2.4.1Java栈------操作数栈
---------java没有寄存器,所有参数传递使用操作数栈
局部变量0,1,2分别为a,b,c;
开始之前0,1,2分别为100,98,0;执行了iload_0,就把局部变量0放入操作数栈,同理iload_1,也放入操作数栈,然后执行iadd,现将两者出栈,相加后的结果放入操作数栈,执行istore_2将结果198弹出操作数栈,存储在局部变量2中
2.4.2Java栈-栈上分配
栈上分配不会出现内存泄漏,函数调用完成自动清理
堆上分配会引起内存泄漏,就是对象创建出来之后,忘记回收。
两次的不同结果表明,第二次在堆上分配,发生了好多GC日志,说明内存不足,需要GC,但是第一次是栈上分配,函数调用完自动清理
栈上分配原则
-小对象(一般几十byte),在没有逃逸情况下,(逃逸:这个对象不仅在你这个线程中使用,还要在其他线程中使用,就不可分配在栈上)可以直接分配栈上,栈是线程私有的
-直接分配在栈上,可以自动回收,减轻GC压力
-大对象或者逃逸对象无法在栈上分配
2.5 栈、堆、方法区交互
栈中保存sample对象的引用test1,sample实例对象是在堆中,而sample的一些信息是在方法区中保存的,这就是三者之间的关系
3.内存模型
-每一个线程有一个工作内存和主存独立
-工作内存存放主存中变量的值的拷贝
当数据从主存中复制到工作内存时,必须出现两个动作,①主存执行read操作,②工作内存执行load操作;
当数据从工作内存拷贝到主存时,也要出现两个动作:①由工作内存执行store操作②有主存执行write操作。
每个操作都是原子的,执行期间不会被中断,但是操作之间可以被中断
对于普通变量,一个线程中更新的值,不能马上反应在其他变量中。
如果需要在其他线程中立即可见,需要用volatile关键字,即直接跳过线程工作内存,直接从主存中存取东西
线程总是在本地内存中,存取变量,而本地内存中包含有共享变量的副本,共享变量本身是在主存中的,Java内存模型(Java Memory Model, JMM)定义程序中各个变量的访问规则即在虚拟机中将变量存储到主存和从主存中取出变量这样的底层细节。控制共享变量副本的更新,因此在本地内存中的共享变量的副本与主存中的共享变量之间的变化存在一定的延时和误差 。
2.6编译和解释运行的概念
解释运行
-解释执行以解释方式运行字节码
-解释执行的意思是:读一句执行一句
编译运行(JIT)
-将字节码编译成机器码
-直接执行机器码
-运行时编译
-编译后性能有数量级的提升
本文只是简单介绍了相关概念,后面会更加详细的了解,各模块的内容的