JVM内存分为哪几个区,每个区的作用是什么? ​

2020-05-14 17:59发布

3条回答
信阳彭于晏
2楼 · 2020-05-14 18:09

JVM主要分以下几个区:

方法区

a.很少发生来垃圾回收,但是并不代表不发生GC,在这里进行的GC主要是对方法区里的常量池和对类型的卸载。b.主要用来存储_已被虚拟机加载_的类的信息常量、静态变量和即时编译器编译后的代码等数据。c.该区域是被线程共享的。d.方法区里有一个运行时常量池,用于存放静态编译产生的字面量和符号引用。该常量池具有动态性,也就是说常量并不一定是编译时确定,运行时生成的常量也会存在这个常量池中。

虚拟机栈(栈内存)

a.为java方法服务。b.是线程私有的,生命周期和线程相同。c.局部变量表中存储的是基本数据类型,返回地址类型和对象引用。d.操作数栈是用来存储运算结果及运算的操作数,通过压栈和出栈的方式。e.每个栈帧都有一个指向运行时常量池中所属方法的引用,是为了方法调用过程中的动态连接。

本地方法栈

和虚拟机栈类似,为本地方法服务。

所有线程共享的一块内存,在虚拟机启动时创建,几乎所有对象实例都在这里创建,这里经常发生垃圾回收操作

程序计数器

内存空间小,各种指令发生的跳转都依赖这个计数器完成。是唯一一个java虚拟机规范没有任何OOM情况的区域。

 


  关于类加载机制,有几点大家需要搞明白:

  什么情况下会触发类的加载?

  类加载的过程有哪些?每个过程分别是干什么的?譬如验证、准备和解析阶段分别是干什么?

  更要明白准备阶段和初始化阶段,虚拟机是如何为类分配内存空间的?

  类加载器的规则是什么?

  JVM内存区域

  了解完JVM的类加载机制之后,还要了解一下JVM的内存区域是怎么划分的,这也是互联网公司面试必问的点。

  那到底JVM的内存区域是怎么划分的呢?

  JVM内存区域主要包含:方法区 程序计数器 Java虚拟机栈 本地方法栈 Java堆,如下图:


  

       1、方法区:

  方法区在JDK1.8之后把名字改成了“Metaspace",可以翻译成"元数据空间",这是一块线程共享的内存空间,主要用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。

  Java虚拟机规范将方法区描述为堆的一个逻辑部分,但它有一个别名”Non-Heap 非堆“ 用于与Java堆区分。

  很多人愿意把方法区成为”永久代“,本质上两者并不等价。HotSpot虚拟机 团队选择把GC分代收集扩展至方法区,或者说使用永久带实现方法区而已。

  方法区存在的问题:

  永久代容易遇到内存溢出问题(HotSpot永久代有-XX:MaxPermSize上限)

  当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常

  运行时常量池也是方法区的一个部分,主要用于存放编译器生成的各种字面量和符号引用。类加载后会进入方法区的运行时常量池

  运行时常量池存在的问题:

  当常量池无法再申请到内存空间时会抛出OutOfMemoryError异常

  2、虚拟机栈

  虚拟机栈是线程私有的内存空间,其生命周期与线程相同,是用于Java方法执行的内存模型。方法执行时会创建栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等。

  虚拟机栈存在的问题:

  线程请求的栈深度大于虚拟机所允许的深度,抛出StackOverflowError异常

  虚拟机栈动态扩展时无法申请到足够的内存,抛出OutOfMemoryError异常

  3、本地方法栈

  其发挥的作用和存在的问题与Java虚拟机栈类似,这里主要说一下其区别。其区别主要是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈为虚拟机使用到Native方法服务。

  知识点:Hotspot虚拟机中将本地方法栈与虚拟机栈合二为一。

  4、Java堆

  Java堆是虚拟机中占内存最大的一块内存空间,是所有线程共享的内存区域,当虚拟机启动的时候就会创建。它的作用主要是存放对象实例,几乎所有的对象实例都在这里分配内存。我们来看下Java虚拟机规范是怎么描述它的:

  所有的对象实例以及数组都要在堆上分配,但是随着JIT编译器的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化发生,所有的对象都分配到堆上也渐渐变得不是那么”绝对“了。

  这一块内存空间也是垃圾收集器管理的主要区域,所以有时候也被称为”GC堆“。

  Java堆存在的问题:

  如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。

  5、程序计数器

  程序计数器是线程私有的一块占用较小的内存空间,主要用于记录当前线程执行到哪里了。而且这也是唯一一个没有内存溢出的区域。

  6、直接内存

  除了以上几块内存空间外,还有一块内存空间就是直接内存,它不属于运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但是这部分频繁使用也可能导致OutOfMemoryError异常。NIO可以使用Native函数库直接分配堆外内存空间。

  文末小结

  关于jvm内存区域空间要重点关注方法区,程序计数器,Java虚拟机栈和Java堆这些内存区域的作用。只有在了解了虚拟机是怎么使用内存的之后,才能在出现内存溢出和泄漏时更快速的定位和排查解决问题。

  

老易
4楼 · 2021-12-24 15:17

ava 虚拟机主要分为以下一个区:


方法区:


1. 有时候也成为永久代,在该区内很少发生垃圾回收,但是并不代表不发生 GC,在这里


进行的 GC 主要是对方法区里的常量池和对类型的卸载


2. 方法区主要用来存储已被虚拟机加载的类的信息、常量、静态变量和即时编译器编译后


的代码等数据。


3. 该区域是被线程共享的。


4. 方法区里有一个运行时常量池,用于存放静态编译产生的字面量和符号引用。该常量池


具有动态性,也就是说常量并不一定是编译时确定,运行时生成的常量也会存在这个常量


池中。


虚拟机栈:


1. 虚拟机栈也就是我们平常所称的栈内存,它为 java 方法服务,每个方法在执行的时候都


会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接和方法出口等信息。


2. 虚拟机栈是线程私有的,它的生命周期与线程相同。


3. 局部变量表里存储的是基本数据类型、returnAddress 类型(指向一条字节码指令的地


址)和对象引用,这个对象引用有可能是指向对象起始地址的一个指针,也有可能是代表


对象的句柄或者与对象相关联的位置。局部变量所需的内存空间在编译器间确定


4.操作数栈的作用主要用来存储运算结果以及运算的操作数,它不同于局部变量表通过索


引来访问,而是压栈和出栈的方式


5.每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了


支持方法调用过程中的动态连接.动态链接就是将常量池中的符号引用在运行期转化为直接


引用。


本地方法栈


本地方法栈和虚拟机栈类似,只不过本地方法栈为 Native 方法服务。



java 堆是所有线程所共享的一块内存,在虚拟机启动时创建,几乎所有的对象实例都在这


里创建,因此该区域经常发生垃圾回收操作。


程序计数器


内存空间小,字节码解释器工作时通过改变这个计数值可以选取下一条需要执行的字节码


指令,分支、循环、跳转、异常处理和线程恢复等功能都需要依赖这个计数器完成。该内


存区域是唯一一个 java 虚拟机规范没有规定任何 OOM 情况的区域。


相关问题推荐

  • 回答 156

    对于每一位才开始接触JAVA的新手来说,先不要管算法和数据结构,大多数简单的程序不需要用到算法和数据结构,所以当你真正需要时再去学习。编程一段时间以后,你就会知道在哪些地方用到他们。这时知道算法的名字并了解它们的功能,然后动手去实践。当我们在去...

  • 回答 93

    2个都很好就业,更关键的是要学得到东西

  • 回答 12
    已采纳

    获取Map集合中所有的key可以通过map集合的keySet()方法获取例如:    Map map = new HashMap();    map.put(xx,xx); //存放数据    //.... 省略    Set set = map.keySet();    //可以通过迭代器进行测试    Iterator iter = set.iter...

  • 回答 56
    已采纳

    不同年龄,不同掌握程度,学历,找工作城市,面试能力这是一个多方面影响的结果,如果是平均值的话,全国平均薪资14k左右

  • 回答 38

    具体学多久,根据自己的学习力,自律性、解决问题能力来决定若系统性学习,跟着讲师的节奏走,大概半年左右,有专业的讲师把课程进行规划,尽心系统学习,有问题,讲师会帮忙解决,学习的效率很高,避免了自学中出现各种问题解决不了,而耽误很多时间,可能会...

  • 回答 23
    已采纳

    (1)idea启动时会有两个快捷方式,安装完后默认生成在桌面的是32位的idea的快捷方式,如果我们使用这个快捷方式运行大项目,一般都会很卡。解决方法是找到idea的安装目录,然后进入bin文件夹,找到名称为idea64的应用程序,右键他生成桌面快捷方式。以后每次...

  • BIO与NIO、AIO的区别2020-05-19 15:59
    回答 4
    已采纳

    IO的方式通常分为几种,同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。一、BIO     在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket来对服务端进行通信,默认情况下服务端需要...

  • Java方法的命名规则2021-04-06 19:07
    回答 31

    ava是一种区分字母的大小写的语言,所以我们在定义变量名的时候应该注意区分大小写的使用和一些规范,接下来我们简单的来讲讲Java语言中包、类、变量等的命名规范。(一)Package(包)的命名Package的名字应该都是由一个小写单词组成,例如com、xuetang9、compan...

  • 回答 2

    public class Point {    private int x;    private int y;    public int getX() {        return x;    }    public void setX(int x) {        this.x = x;    }    public int getY() {        return y;    } ...

  • 回答 6

    经典版单例模式public class Singleton {        private static Singleton uniqueInstance;//利用一个静态常量来记录singleton类的唯一实例。     private Singleton() {     }     public static  Singleton getInstance()...

  • 回答 3

    哈希表的长度一般是定长的,在存储数据之前我们应该知道我们存储的数据规模是多大,应该尽可能地避免频繁地让哈希表扩容。但是如果设计的太大,那么就会浪费空间,因为我们跟不用不到那么大的空间来存储我们当前的数据规模;如果设计的太小,那么就会很容易发...

  • 回答 14

    1. DOM(Document Object Model)        DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准。DOM是以层次结构组织的节点或信息片断的集合。这个层次结构允许开发人员在树中寻找特定信息。分析该结构通常需要加载整个文档和构造层次结构,然后才...

  • 回答 19

    1)作用不同: throw用于程序员自行产生并抛出异常; throws用于声明在该方法内抛出了异常2) 使用的位置不同: throw位于方法体内部,可以作为单独语句使用; throws必须跟在方法参数列表的后面,不能单独使用。3)内容不同: throw抛出一个异常对象,且只能是...

  • 回答 11

    基本执行过程如下:1)程序首先执行可能发生异常的try语句块。2)如果try语句没有出现异常则执行完后跳至finally语句块执行;3)如果try语句出现异常,则中断执行并根据发生的异常类型跳至相应的catch语句块执行处理。4)catch语句块可以有多个,分别捕获不同类型...

  • 回答 20

    100-199 用于指定客户端应相应的某些动作。 200-299 用于表示请求成功。 300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息。 400-499 用于指出客户端的错误。 400 语义有误,当前请求无法被服务器理解。 401 当前请求需要用户验证...

  • 回答 16

    异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题通常就不会发生。受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。Java编译...

没有解决我的问题,去提问