一、Jvm体系结构?以及一个.java文件的执行过程
类加载器,运行时数据区,执行引擎、本地方法接口
首先通过类加载器(ClassLoader)会把 Java 代码转换成字节码,
运行时数据区(Runtime Data Area)再把字节码加载到内存中,而字节码文件只是 JVM 的一套指令集规范,并不能直接交个底层操作系统去执行,
因此需要特定的命令解析器–执行引擎(Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行,
而这个过程中需要调用其他语言的本地库接口(本地方法接口Native Interface)来实现整个程序的功能。
二、Jvm运行时区域?
程序计数器,方法区,栈,堆,本地方法栈,
程序计数器:线程私有的;是一个指针;指向方法区中的方法字节码(用来存储指向下一条指令的地址,也即将要执行的指令代码),由执行引擎读取下一条指令,是一个非常小的内存空间
java虚拟机栈: 线程私有的,每个线程都会创建一个栈;生命周期与线程相同。虚拟机栈描述的是方法执行的内存模型:每个方法的执行都会创建一个栈帧(stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每个方法呗调用直至执行完毕的过程,就对应一个栈帧在虚拟机中从入栈到出栈的过程。局部变量表存放了编译器可知的各种java虚拟机基本数据类型(8种)、对象引用(不一定是对象本身,也可是一个指向起始地址的引用指针,也可是指向一个代表对象的句柄或其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。
这些数据类型在局部变量表中的存储空间以局部变量槽(slot)来表示,其中64位长度的long和double类型的数据会占用两个变量槽,其他的数据类型只会占用一个。局部变量表所需的内存空间是完全正确的,在方法运行期间不会改变局部变量表的大小(大小是指变量槽的数量,虚拟机真正使用多大的内存空间(比如一个槽占用32bit、64bit或者更多)来实现一个变量槽,这完全由具体的虚拟机实现自行决定的事情)。
遵循后进先出原则(递归调用原理分析后续可以讲一下);是一个连续的内存空间。
有两类异常:1、如果线程请求的栈深度(每次方法调用都会有一个栈帧压入虚拟机栈,操作系统给jvm分配的内存是有限的。如果方法调用过多,导致虚拟机满了就会溢出,这里栈帧深度就是指栈帧的数量)大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果java虚拟机栈容量可以动态扩展,当栈扩展时无法申请到足够的内存会抛出OutOfMemoryError异常。
本地方法栈(Native Method Stacks):与虚拟机栈发挥的作用相似,区别是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机栈使用到本地方法(native)服务。也即保存被native修饰的方法,即非java方法。
java堆:堆是被所有线程共享的一块内存区域,并且是虚拟机管理内存最大的一块。在虚拟机启动时创建;这个内存区域的唯一目的是用来存放对象实例,java世界“几乎”所有的对象实例都在这里分配内存,垃圾收集器就是收集这些对象,然后根据GC算法回收。是个不连续的内存空间。
如果在java堆中没有内存完成实例分配,并且堆也无法再扩展时,java虚拟机将会抛出OutOfMemoryError异常。
堆内存分为新生代(Young Generation)和老年代(Old Generation)。新生代又分为伊甸区(Eden)和幸存者区(Survivor)。幸存者区由幸存者0区(FromSpace)和幸存者1区(ToSpace)组成。伊甸区和幸存者0、1区默认比例是8:1:1。
新生成的对象首先放到新生代的伊甸区,当伊甸区空间满了,触发Minor GC,存活下来的对象移动到幸存者0区,幸存者0区满后触发执行Minor GC,幸存者0区存活对象移动到幸存者1区,这样保证了一段时间内总有一个幸存者区为空。经过多次Minor GC仍然存活的对象移动到老年代。
老年代存储长期存活的对象,占满时会触发Major GC=Full GC(此处Major GC是清理老年代垃圾并触发minor GC清理新生代垃圾还是Major GC既清理老年代也新生代垃圾,我要查一下),GC期间会停止所有线程等待GC完成,所以对响应要求高的应用尽量减少发生Major GC,避免响应超时。
Minor GC : 清理年轻代
Major GC : 清理老年代
Full GC : 清理整个堆空间,包括年轻代和永久代
所有GC都会停止应用所有线程。
方法区 :*方法区是线程共享的。*比如:类的代码、静态变量、运行时常量池。
方法区在jdk1.7以前,习惯上把方法区称为永久代(习惯上),而到了JDK8,终于完全废弃了永久代的概念,在本地内存中实现的元空间(Metaspace)来代替。这两个最大的区别就是:元空间不在虚拟机设置的内存中,而是使用本地内存。
如果方法区无法满足新的内存分配需求时,将抛出OutOfMemoryError异常。
hello,读者,本人第一次发表博客,以前总是将知识点记在自己的小本本上,这次尝试将自己所掌握的知识公之于众(希望不要贻笑大方哈哈),主要目的就是希望大家一起分享知识,一起进步,感谢您看到了这里。有任何建议,请留言指教!
ps:主要是看了《深入理解java虚拟机》后的一些感悟
9万+

被折叠的 条评论
为什么被折叠?



