基于深入理解JVM上个人笔记,不确定对。
1. 主要记录内存方面的,,,
管理的内存主要有:方法区、虚拟机栈、本地方法栈、堆,程序计数器
程序计数器:记录虚拟机指令字节码地址,执行的下一条指令、每个线程都有独立。(native时,技术值为空)
java虚拟机栈:线程私有,生命周期等同线程,储存方法内存模型,局部变量表、,调用和完成=入栈和出栈。
本地方法栈:与java虚拟机栈相似,执行其他语言(c/c++/other)
Java堆(Heap):线程共享,几乎所有对象和数组存在里面。
方法区:线程共享,储存已被加载的类信息、常量(final)、静态变量(static)、包括运行时常量词。
e.g. 在main方法中,int a ; a =1; 主线程:Java虚拟机栈将main方法入栈,包含变量表(int),和操作数栈(指令),程序计数器从操作数栈中逐一执行。
在main方法中,调用其他方法fun(),入栈,执行完毕出栈
在main方法中,Person person= new Person(); person.a=1;入栈、类加载,在java堆中分配内存,在方法区记录类信息((new)Person),程序计数器下跳,此报告虚拟机栈中main方法局部变量表引用,找到person在堆的地址和在方法区的类信息,堆中内存a值更改。出栈。
类/成员变量储存位置 int a; 类在类加载时被分配在java堆。Person p;类加载时分配在java堆,存放引用值,指向其被加载时堆地址。String s = "ss",String应该也是引用值,大多数指向方法区的常量词。static int a;应该在方法区,应该编译时就存入。static Person p;引用值存在方法区。
private final int 和final Person 不知道放在哪、还有void fun()在入栈前在存在哪的,还是说编译时就已经建立好虚拟机栈了?所以初定的结构式,应该都存在类加载时的java堆里,而通过成员变量找到。static void fun()应该在方法区。
垃圾收集器最主要是要收集堆,并非是持有引用就不回收,而是被引用链可到GC ROOTS,GC通过可达性分析。
收集算法和收集器没怎么看懂。暂不理会。
内加载和执行引擎,暂不理会,tomcat实现了自定义类加载器。
运算速度与通信速度差距太大:磁盘IO,网络,数据库等(卧槽,为什么没写内存,明明后面没提到这三个),所以需要高速缓存(Cache),每个处理器都有自己的Cache,又共享主内存(Memory),出现一致性问题,需要协议。Java需要规范一种通用内存模型,达到共平台。这个内存模型按作者说法是与前面堆栈之类的不是一个层次的划分。猜测是偏与硬件对应多一点,工作内存对高速缓存,主内存对内存。然后就是java制定的交互协议对上面的系统协议。lock、unlock、read、load、use、assign(赋值)、store、write。通过rl和sw进行工作内存和主内存交互。volatile具有可见性(线程1 assign普通变量时,需要经过sw到主内存,线程2rl才可以,而volatile修饰时线程2可以立即得知),但不等于线程安全。用于只读判断时作用较多。因为细分成字节码指令时,只有第一条是准确的,运行下一条时,有可能已经发生了改变。volatile第二特性禁止指令重排序优化(重排序,结果正确,但顺序不确定),加不加生成的汇编码有差异,除了单例其他也不建议使用,使用最多的同步锁即可。
synchronized块之前的就具备原子性,可见性:线程1修改共享变量,全线程立即得知,volatile,syn,final。有序性:不懂。应该与重排序优化相关?
java线程使用内核线程实现,1:1,抢占式线程调度。
还需要做的建议:1.重读并尝试。2. 一条指令执行的完整过程(编写java代码-编译中间class-虚拟机解析-汇编-指令集?-输入)3.JVM告一段落