我这个人比较懒散,一切随缘的态度,感觉自己都可以出家了O(∩_∩)O哈哈哈~,不过认真地说:我对于技术的热爱和文学的态度还是挺认真的。最近比较老气(原因:读了西游记原著,注意是原著不是白话文哈,被洗脑了)尴尬,其实不应该说出来的,但是还是很想推荐大家去图书馆看看这本比砖块大比砖块厚的书,其书年代:明(超级久远对不对?正好适合你们这些小鲜肉)作者大大是吴承恩老先生(看书小建议:不要看序和评论,不然看完你就完了;记得读书时候看了《格列佛游记》,着实服了自己看书这么认真干嘛?一个都不放过把开篇导语一字不漏的看完了,然后我再也不能拿它当童话故事看?深深的罪恶感啊!!!)
班门弄斧了,开了个小差,回归正题:JVM(Java虚拟机),字面上意思:虚构出来的计算机,不过它有自己完善的硬件架构、处理器、堆栈什么的......(注:Java的可移植性就是建立在此基础上的)。还记得学Java时特别火的一句话“一次编译,多次运行”,现在来说其大概意思就是:任何平台只要装有针对于该平台的Java虚拟机,字节码文件(.class)就可以在该平台上运行。很强大有木有?其实JRE是由Java API和JVM组成,其过程就是:JVM通过类加载器(Class Loader)加类Java应用,并通过Java API进行执行(说个小秘密,见图说话)
如图所示,JDK里面就包含JRE,所以这就是为什么学习Java一定要深入了解JVM底层原理(一脸认真,其实我还不太懂)接着往下说:JVM内存的分区,它到底分哪几个区呢?每个区的作用又是什么?
开始讲,敲黑板!!!
方法区:有时候也会成为永久代,很少发生垃圾回收(有可能发生GC,不过一般在这里发生的GC主要是对方法区里的常量池和类型的卸载),该区域是被线程共享的,而该区的运行时常量池,也就是说常量并不一定是编译时确定,运行时生成的常量也会存在这个常量池中。
虚拟机栈:是线程是私有的,它的生命周期与线程相同,它主要用于存储局部变量表、操作数栈、动态链接和方法出口......重点讲解局部变量表: 局部变量表里存储的是基本数据类型、returnAddress类型(指向一条字节码指令的地址)和对象引用,这个对象引用有可能是指向对象起始地址的一个指针,也有可能是代表对象的句柄或者与对象相关联的位置
引入新知识:
对象的访问定位:使用对象时,通过栈上的 reference 数据来操作堆上的具体对象。
两种访问:
1.通过句柄访问:Java 堆中会分配一块内存作为句柄池。reference 存储的是句柄地址。
2.使用直接指针访问:reference 中直接存储对象地址
比较:
使用句柄的最大好处是 reference 中存储的是稳定的句柄地址,在对象移动(GC)是只改变实例数据指针地址,reference 自身不需要修改。
直接指针访问的最大好处是速度快,节省了一次指针定位的时间开销。
如果是对象频繁 GC 那么句柄方法好,如果是对象频繁访问则直接指针访问好。
最后说一句:局部变量所需的内存空间在编译器间确定。
而操作数栈的作用主要用来存储运算结果以及运算的操作数,它不同于局部变量表通过索引来访问,而是压栈和出栈的方式。弱弱的说一声:每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接.动态链接就是将常量池中的符号引用在运行期转化为直接引用。