JVM的内存区域都说不清楚真能找到好工作吗?

        对于 Java 程序员来说,在虚拟机自动内存管理机制下,不再需要像 C/C++程序开发程序员这样为每一个 new 操作去写对应的 delete/free 操作,不容易出现内存泄漏和内存溢出问题。正是因为 Java 程序员把内存控制权利交给 Java 虚拟机,一旦出现内存泄漏和溢出方面的问题,如果不了解虚拟机是怎样使用内存的,那么排查错误将会是一个非常艰巨的任务。

运行时数据区域

jdk1.8之前:

        在jdk1.8之后方法区被安排到了直接内存区域的元空间中。

线程私有的:

  • 程序计数器
  • 虚拟机栈
  • 本地方法栈

线程共享的:

  • 方法区
  • 直接内存 (非运行时数据区的一部分)

 程序计数器

         程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的信号指示器。字节码解释器工作通过改变这个计数器的值来选取下一条需要执行的字节码指令,分子、循环、跳转、异常处理、线程恢复等功能都需要依赖这个计数器来完成

    另外,为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,个线程之间计数器互不影响,独立存储,我们称这类内存区域为“线程私有”内存

    主要有两个作用:

        1.字节码解释器通过改变程序计数器来依次读取指令,从而实现代码的流程控制,如:顺序执行、选择、循环、异常处理。

        2.在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而当线程被切换回来的时候能够知道该线程上次运行到哪儿了。
 

虚拟机栈

        Java虚拟机栈,早期也叫Java栈。每个线程在创建时都会创建一个虚拟机栈。其内部保存一个个的栈帧,对应着一次次的Java方法调用,其生命周期和线程一致,且线程私有的。

        Java虚拟机栈的作用:主管Java程序运行,它保存方法的局部变量、部分结果、并参与方法的调用和返回。每个线程都有自己的栈,栈中的数栈帧的据都是以格式存在。

 

栈的特点(优点):

  • ​ 栈是一种快速有效的分配存储方式,访问速度仅次于程序计数器
  • ​ JVM直接对java栈的操作只有两种:每个方法执行,伴随着进栈(入栈,压栈)
  • ​ 执行结束后的出栈工作
  • ​ 对于栈来说不存在垃圾回收问题

本地方法栈

        本地方法栈的功能和特点类似于虚拟机栈,均具有线程隔离的特点以及都能抛出栈溢出异常和OutOfMemoryError异常。不同的是,本地方法栈服务的对象是JVM执行的native方法,而虚拟机栈服务的是JVM执行的java方法。

方法区

        方法区(Method Area)与Java堆一样,是各个线程共享的内存区域。方法区在JVM启动的时候被创建,并且它的实际的物理内存空间中和Java堆区一样都可以是不连续的。方法区的大小,跟堆空间一样,可以选择固定大小或者可扩展。方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法区溢出,虚拟机同样会抛出内存溢出错误:ava.lang.OutofMemoryError:PermGen space 或者java.lang.OutOfMemoryError:Metaspace
比如加载大量的第三方的jar包,Tomcat部署的工程过多(30~50个),大量动态的生成反射类。关闭JVM就会释放这个区域的内存。

        栈是运行时的单位,而堆是存储单位:栈解决程序运行问题,即程序如何执行,或者说如何处理数据。堆解决的是数 据存储问题,即数据怎么放,放在哪儿。堆区的大小是可以调节的,但是Java堆区在JVM启动时就被创建,其大小也就确定了。并且是JVM中管理的最大的一块内存空间。在堆中创建的对象要等到GC的发生才能被移除。

        经研究表明70%-99%的对象属于临时对象,为了提高GC的性能,Hotspotx虚拟机又将堆区进行了进一步划分。被分为三部分:新生区、养老区、永久区 。将对象根据存活概率进行分类,对存活时间长的对象,放到固定区,从而减少扫描垃圾时间及GC频率。针对分类进行不同的垃圾回收算法,对算法扬长避短。为此,堆空间才被分为新生代和老年代,并将生命周期很短的对象放在新生代,将生命周期很长的对象放在老年代,因为在每次GC时,垃圾回收器都会去判断当前对象是否可以被回收,而这些生命周期很长的对象每次都被垃圾回收器扫描,但每次都不回收,故而可以将这些对象放在老年代,并减少对老年代的GC次数,从而将GC的重心放在新生代上。 

通过两个JVM参数可以设置堆的初始内存和最大内存:

  • -Xms:设置堆的初始内存

  • -Xmx:设置堆的最大内存

默认情况下

  • 初始内存大小:物理电脑内存大小 / 64
  • 最大内存大小:物理电脑内存大小 / 4

一旦堆区中的内存大小超过“-Xmx"所指定的最大内存时,将会抛出OutOfMemoryError异常。 

猜你喜欢

转载自blog.csdn.net/m0_58366209/article/details/128217078