JVM(堆和栈)内存分配

什么是JVM?

JVM就是JAVA虚拟机,Java的特点“一次编译,到处运行”,这就是JVM做到的,JVM是一台虚拟的计算机,把具体的机器指令屏蔽起来,用自己独有的一套东西,开发者编写的程序经过编译器生成Java虚拟机上运行的目标代码(字节码),就可以无视平台,带来的弊端就是Java虚拟机在执行字节码时,也需要把字节码解释成具体平台上的机器指令执行。

JVM原理

JVM是Java的核心和基础,在编译器和OS平台之间的虚拟处理器,它是一种利用软件方法实现的抽象的计算机基于下层操作系统和硬件平台,可以在上面执行Java的字节码程序。

JVM(堆和栈)内存分配_第1张图片

 Java编译器只要面向JVM,生成JVM能理解的代码或字节码文件。Java源文件经编译成字节码程序,通过JVM将每一条指令翻译成不同平台机器码,通过特定平台运行。

JVM内存

JVM将内存划分为方法区、堆、程序计数器、虚拟机栈(也叫JAVA方法栈)、本地方法栈,其中方法区和堆是线程共享的,虚拟机栈、本地方法栈、程序计数器是非线程共享的。JVM(堆和栈)内存分配_第2张图片

为什么要分为线程共享和非线程共享?

一个一般性的Java程序的工作过程是这样的:一个Java源程序文件,会被编译为字节码文件(以class为扩展名),每个Java程序都需要运行在自己的JVM上,然后告知JVM程序的运行入口,在被JVM通过字节码解释器加载运行。那么程序开始运行后, 如何涉及到各个内存区域呢?

首先,JVM初始运行的时候会分配好方法区,而JVM每遇到一个线程,就为其分配一个程序计数器、虚拟机栈和本地方法栈,当线程终止时,三者(虚拟机栈、本地方法栈和程序计数器)所占的内存空间就会被释放掉。这就是为什么要把内存区域分成线程共享和非线程共享的原因,非线程共享的那三个区域的生命周期与所属线程相同,而线程共享的区域与JAVA程序运行的生命周期相同,所以这也就是系统垃圾回收的场所只发生在线程共享的区域的原因。

堆(Heap),是JVM用来存储对象实例以及数组值的区域,可以认为Java中所有通过new创建的对象的内存都在此分配,堆中的对象的内存需要的等待GC进行回收。

JVM(堆和栈)内存分配_第3张图片

 1、堆是JVM中所有线程共享的,因此在其上进行对象内存的分配均需要进行加锁,这也导致了new对象的开销比较大的

2、Sun Hotspot JVM为了提升对象内存分配的效率,对于所创建的线程都会分配一块独立的空间TLAB(Thread Local Allocation Buffer),其大小由JVM根据运行的情况计算而得,在TLAB上分配对象时不需要加锁,因此JVM在给线程的对象分配内存时会尽量的在TLAB上分配,在这种情况下JVM中分配对象内存的性能和C基本一样高效的,但如果对象过大的话则依然是直接使用堆空间分配

3、TLAB仅作用于新生代的Eden Space,因此在编写Java程序时,通常多个小的对象比大的对象分配起来更加高效。

4、所有新创建的Object都将会存储在新生代Yong Generation中。如果Young Generation的数据在一次或多次GC后存活下来,那么将被转移到OldGeneration。新的Object总是创建在Eden Space。 

方法区域(Method Area)存放了所加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Fiedld信息、类中的方法信息,当开发人员在程序中通过Class对象中getName、isInterface等方法来获取信息时,这些数据都来源于方法区域,同时方法区域也是全局共享的,在一定条件下它也会被GC,当方法区域需要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。

本地方法栈,存放每个native方法的调用状态。

程序计数器,是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行。

虚拟机栈,描述的是Java方法执行的内存模型,用于存储局部变量,操作数栈,动态链接,方法出口等信息。

JVM垃圾回收

GC的基本原理:将内存中不再被使用的对象进行回收,GC中用于回收的方法称为收集器,由于GC需要消耗一些资源和时间,Java在对对象的生命周期特征进行分析后,按照新生代、老年代的方式来对对象进行收集,以尽可能的缩短GC对应用造成的暂停

1、对新生代的对象的收集称为minor GC

2、对老年代的对象收集称为Full GC

3、程序中主动调用System.gc()强制执行的GC为Full GC

4、不同的对象引用类型,GC会采用不同的方法进行回收,JVM对象的引用分为四种类型:

(1)强引用:默认情况下,对象采用的均为强引用(这个对象的实例没有其他对象引用,GC时才会被回收)

(2)软引用:软引用是Java中提供的一种比较适合于缓存场景的应用(只有在内存不够用的情况下才会被GC)

(3)弱引用:在GC时一定会被GC回收

(4)虚引用:由于虚引用只是用来得知对象是否被GC

你可能感兴趣的:(学习足迹)