java运行时内存

总说java是一次编译,处处运行的语言,也即java的平台无关性。那么,究竟是谁帮咱们干脏活累活,由于咱们知道不论是什么语言,最终都要翻译成底层的机器码才能真正在计算机上运行,那么不一样的操做系统,不一样的cpu架构,必然致使机器码的不一样,是谁这么好心?JRM,Java Runtime Environment,针对不一样的操做系统和硬件架构,会有不一样的JRM来适配。当咱们将本身的java程序在某个平台上运行的时候,会派生出一个JVM,Java Virtual Machine,他实际是JRM的一部分,经过在其中仿真模拟各类计算机功能来实现的用户的意图。因此,真正在使用的时候,了解JVM是java程序员必不可少的技能。html

jvm的功能java

JVM的输入即为上图的class文件,输出即为对操做系统的硬件的调用。程序员

JVM实例对应了一个独立运行的java程序,它是进程级别 。
a) 启动。启动一个Java程序时,一个JVM实例就产生了,任何一个拥有public static void main(String[] args)函数的class均可以做为JVM实例运行的起点 。数组

b) 运行。main()做为该程序初始线程的起点,任何其余线程均由该线程启动。JVM内部有两种线程:守护线程和非守护线程,main()属于非守护线程,守护线程一般由JVM本身使用,java程序也能够代表本身建立的线程是守护线程 。
c) 消亡。当程序中的全部非守护线程都终止时,JVM才退出;若安全管理器容许,程序也可使用Runtime类或者System.exit()来退出 。安全

在类的具体加载执行的过程当中:多线程

首先面临的是加载器对class文件的一系列工做,当发现类文件合法安全有效以后,就能够在运行时环境进行分配,而后具体的执行过程有执行引擎来真正运行。架构

在java程序员平常讨论中说起的堆和栈,其实都在runtime data area中。jvm

 

如上图,堆和方法区是jvm中全部线程能够共享的,可是java栈,本地方法栈,程序计数器,是线程独享的。函数

a) 程序计数器(PC寄存器)操作系统

因为在JVM中,多线程是经过线程轮流切换来得到CPU执行时间的,所以,在任一具体时刻,一个CPU的内核只会执行一条线程中的指令,所以,为了可以使得每一个线程都在线程切换后可以恢复在切 换 以前的程序执行位置,每一个线程都须要有本身独立的程序计数器,而且不能互相被干扰,不然就会影响到程序的正常执行次序。所以,能够这么说,程序计数器是每一个线程所私有的。因为程序计数器中存储的数据所占空间的大小不会随程序的执行而发生改变,所以,对于程序计数器是不会发生内存溢出现象(OutOfMemory)的。

b) java栈

 Java栈中存放的是一个个的栈帧,每一个栈帧对应一个被调用的方法,在栈帧中包括局部变量表(Local Variables)操做数栈(Operand Stack)、指向当前方法所属的类的运行时常量池(运行时常量池的概念在方法区部分会谈到)的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些额外的附加信息。当线程执行一个方法时,就会随之建立一个对应的栈帧,并将创建的栈帧压栈。当方法执行完毕以后,便会将栈帧出栈。

c)本地方法栈

本地方法栈与Java栈的做用和原理很是类似。区别只不过是Java栈是为执行Java方法服务的,而本地方法栈则是为执行本地方法(Native Method)服务的

d)堆

Java中的堆是用来存储对象自己的以及数组(数组引用是存放在Java栈中的)。堆是被全部线程共享的,在JVM中只有一个堆。

e)方法区

与堆同样,是被线程共享的区域。在方法区中,存储了每一个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。在Class文件中除了类的字段、方法、接口等描述信息外,还有一项信息是常量池,用来存储编译期间生成的字面量和符号引用。在方法区中有一个很是重要的部分就是运行时常量池,它是每个类或接口的常量池的运行时表示形式,在类和接口被加载到JVM后,对应的运行时常量池就被建立出来。固然并不是Class文件常量池中的内容才能进入运行时常量池,在运行期间也可将新的常量放入运行时常量池中,好比String的intern方法。

方法区可能还有不一样的名字,好比永久代,或者元信息空间,其实指的都是方法区。

 

java虽然解放了程序员对于空间申请释放的繁琐劳动,但若是不了解OOM的种类,也会致使在做业出问题时不知道如何处理。

能够看出,除了程序计数器不会抛出oom外,其余几个部分都会可能致使OOM。

另外,多说一句,咱们在用synchronize关键字时,到底同步的是什么,其实就是从主内存(包括java堆和方法区)向子内存(即java栈和native栈)中刷新数据。

 

 参考:

https://www.cnblogs.com/xing901022/p/7725961.html

https://www.cnblogs.com/fubaizhaizhuren/p/4976839.html

相关文章
相关标签/搜索