展开

关键词

JVM内存模型1 程序计数器2. Java虚拟机栈(JVM Stack)3. 本地方法栈(Native Method Stack)4 Java堆(Java Heap)5 方法区6 直接内存(Direc

(但内存空间可能还有很多),就抛出异常 OutOfMemoryError 若Java虚拟机栈的内存大小允许动态扩展,且当线程请求栈时内存用完了,无法再动态扩展了,此时抛出OutOfMemoryError 堆内存物理上不一定要连续,只需要逻辑连续即可,就像磁盘空间一样. 堆是垃圾回收的主要区域,所以也被称为GC堆. 同样的,对永久代的设置参数 PermSize 和 MaxPermSize 也会失效。 每个类加载器都有它的内存区域-元空间 进行线性分配 不会单独回收某个类(除了重定义类 RedefineClasses 或类加载失败) 没有GC扫描或压缩 元空间里的对象不会被转移 如果GC发现某个类加载器不再存活 关闭钩子本质是一个线程(也称为hock线程),可以通过Runtime的addshutdownhock (Thread hock)向jvm注册一个关闭钩子。

87790

探索 Java 内存管理机制,面试别被问住了

8 种操作又可分为作用于内存的和作用于工作内存的操作。 3.3.1 作用于内存的操作 lock(锁定) 作用于内存的变量,它把一个变量标识为一条线程独占的状态。 线程私有 为了线程切换后能恢复到正确的执行位置,每条线程都有一个私有的程序计数器。 无异常 程序计数器是唯一一个在 Java 虚拟机规范中没有规定任何 OOM 情况的区域。 JVM 规定了栈的最大深度,如果线程请求执行方法时栈的深度大于规定的深度,就会抛出栈溢出异常 StackOverflowError。 异常 与虚拟机栈一样,本地方法栈也会抛出 StackOverflowError 和 OutOfMemoryError 异常。 工作原理 复制算法把可用内存按容量划分为大小相等的两块,每次使用其中的一块。当使用中的这块内存用完了,就把存活的对象复制到另一块内存,然后把已使用的空间一次清理掉。

29321
  • 广告
    关闭

    什么是世界上最好的编程语言?丨云托管征文活动

    代金券、腾讯视频VIP、QQ音乐VIP、QB、公仔等奖励等你来拿!

  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    【Java面试宝典】深入理解JAVA虚拟机

    Java虚拟机规范对这个区域规定了两种异常状况: 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。 本地方法栈区域也会抛出StackOverflowError和OutOfMemoryErroy异常。 1.4 Java堆 堆是Java虚拟机所管理的内存中最大的一块。 Java堆可以处于物理上不连续的内存空间中,只要逻辑是连续的即可。如果在堆中没有完成实例分配,并且堆也无法再扩展时将会抛出OutOfMemoryError异常。 这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载。 当方法区无法满足内存分配需求时,将抛出OutOfMemoryErroy异常。 1.6 运行时常量池 它是方法区的一部分。 当常量池无法再申请到内存时会抛出OutOfMemoryError异常。 1.7 直接内存 直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域

    37310

    【深入Java虚拟机】之一:Java内存区域与内存溢出

    在Java虚拟机规范中,对这个区域规定了两种异常情况: 1、如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。 在单线程的操作中,无论是由于栈帧太大,还是虚拟机栈空间太小,当栈空间无法分配时,虚拟机抛出的都是StackOverflowError异常,而不会得到OutOfMemoryError异常。 而在多线程环境下,则会抛出OutOfMemoryError异常。 下面详细说明栈帧中所存放的各部分信息的作用和数据结构。 方法区域又被称为“永久代”,但仅仅对于Sun HotSpot来讲,JRockit和IBM J9虚拟机中并不存在永久代的概念。 内存溢出 下面给出个内存区域内存溢出的简单测试方法 ? 这里有一点要重点说明,在多线程情况下,给每个线程的栈分配的内存越大,反而越容易产生内存溢出异常

    46960

    基础篇:JVM运行时内存布局

    ,可以在网络获取,也可以实时生成。 栈帧随着方法调用而创建,随着方法结束而销毁(无论方法是正常完成还是异常完成) 如果线程请求的栈深度大于虚拟机允许深度,则抛出StackOverflowError;扩展时无法申请到足够内存,则抛出OutOfMemeryError (HopShot的实现 直接把本地方法栈和虚拟机栈合二为一) 上述3类区域,生命周期与Thread相同,即:线程创建时,相应的内存区创建,线程销毁时,释放相应内存 2.4 堆(Heap) 线程共享的一块内存区域 JVM内存区域是指JVM运行时将内存数据分区域存储,强调对内存空间的划分 JAVA内存模型是Java语言在多线程并发情况下对于共享变量内存操作的规范:解决变量在多线程的可见性、原子性的问题 4 JMM内存模型交互操作 各位有何高见,请指教下 JMM对八种指令的使用,制定了如下规则 read和load、store和write必须顺序执行,而且两个指令绑定出现;就是说出现read就要有load 不允许一个线程丢弃最近的

    19210

    深入了解Java之虚拟机内存

    Register) Java虚拟机栈(VM Stack) 本地方法栈(Native Method Stack) 方法区(method area) 堆(heap) 一、程序计数器 用来指示程序执行哪一条指令,跟汇编语言的程序计数器的功能在逻辑是一样的 在Java虚拟机规范中,对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展 ,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。 与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。 五、方法区 方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、以及编译器编译后的代码等。

    19030

    深入了解 Java 之虚拟机内存

    Register) Java虚拟机栈(VM Stack) 本地方法栈(Native Method Stack) 方法区(method area) 堆(heap) 一、程序计数器 用来指示程序执行哪一条指令,跟汇编语言的程序计数器的功能在逻辑是一样的 在Java虚拟机规范中,对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展 ,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。 与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。 五、方法区 方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、以及编译器编译后的代码等。

    40770

    【107期】谈谈面试必问的Java内存区域(运行时数据区域)和内存模型(JMM)

    虚拟机栈规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出 StackOverflowError 异常;如果虚拟机栈可以动态扩展(当前大部分的 Java 虚拟机都可动态扩展),如果扩展时无法申请到足够的内存 ,就会抛出 OutOfMemoryError 异常。 与虚拟机栈一样,本地方法栈区域也会抛出 StackOverflowError 和 OutOfMemoryError 异常线程开始调用本地方法时,会进入 个不再受 JVM 约束的世界。 垃圾收集行为在这个区域是比较少出现的,其内存回收目标主要是针对常量池的回收和对类型的卸载。当方法区无法满足内存分配需求时,将抛出 OutOfMemoryError 异常。 这里所讲的内存、工作内存与 Java 内存区域中的 Java 堆、栈、方法区等并不是同一个层次的内存划分,这两者基本是没有关系的,如果两者一定要勉强对应起来,那从变量、内存、工作内存的定义来看,内存主要对应于

    26520

    面试必问的JVM知识-JVM特性学习

    如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果Java虚拟机栈容量可以动态扩展,当栈扩展时无法申请到足够的内存会抛出OutOfMemoryError异常 当然,本地方法栈也会在栈深度溢出或者栈扩展失败时分别抛出StackOverflowError和OutOfMemoryError异常。 当然随着技术发展,对象实例也有可能在其他地方分配。 将Java堆细分的目的只是为了更好地回收内存,或者更快地分配内存。 Java堆可以处于物理上不连续的内存空间中,但在逻辑它应该被视为连续的。 垃圾收集行为在这个区域的确是比较少出现的,但并非数据进入了方法区就如永久代的名字一样"永久"存在了。区域的内存回收目标主要是针对常量池的回收和对类型的卸载。 运行时常量池是方法区的一部分,当常量池无法再申请到内存时会抛出OutOfMemoryError异常

    6810

    JVM 运行时的内存分配

    每一条JVM线程都有自己的PC寄存器,各条线程之间互不影响,独立存储,这类内存区域被称为“线程私有”内存在任意时刻,一条JVM线程只会执行一个方法的代码。 如果线程请求的栈深度大于虚拟机所允许的深度将抛出StackOverflowError;如果JVM Stack可以动态扩展,但是在尝试扩展时无法申请到足够的内存时抛出OutOfMemoryError。 本地方法栈抛出异常跟上面的虚拟机栈一样。 4、Java堆(Java Heap)   虚拟机管理的内存中最大的一块,同时也是被所有线程所共享的,它在虚拟机启动时创建,货存在的意义就是存放对象实例,几乎所有的对象实例以及数组都要在这里分配内存。 既然运行时常量池是方法区的一部分,自然会受到方法区内存的限制,当常量池无法再申请到内存时会抛出OutOfMemoryError异常

    29580

    Java 虚拟机内存区域划分详解(1)

    经常有人把 Java 内存区分为堆内存( Heap)和栈内存( Stack),这种分法比较粗糙, Java 内存区域的划分实际远比复杂。 在 Java 虚拟机规范中,对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出 StackOverflowError 异常;如果虚拟机栈可以动态扩展(当前大部分的 Java 与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError 和OutOfMemoryError 异常。 如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出 OutOfMemoryError 异常。 根据 Java 虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出 OutOfMemoryError 异常

    22440

    JVM - 运行时数据区

    这里注意的是如果递归的方法递归的太深很容易抛出下面两种异常,所以递归虽然写起来方便,但是性能会有所下降,并且容易抛出异常。 Java虚拟机规范中,对这个区域规定了两种异常状况 i. 抛出异常和虚拟机栈相同。 4、Java堆 Java堆是与前面的区域不同的是:这个区域是 被所有线程共享 的一块内存区域,用来存放对象实例,并为对象实例分配好内存。 有实例没有被分配,且堆无法再扩展的时候会抛出OutOfMemoryError异常,虚拟机调优其实也主要关注的是这个区域。 这些都在常量池的 UTF-8 表中(逻辑的划分); 运行时常量池 运行时常量池是方法区的一部分,是一块内存区域。Class 文件常量池将在类加载后进入方法区的运行时常量池中存放。 三、直接内存 这个区域并不是属于运行时数据区域,但是这个区域也会被频繁使用,并且抛出OOM异常

    16720

    深入理解java虚拟机学习笔记 -- 1

    在Java虚拟机规范中,对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展 ,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。 与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。 Java堆 Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。 OutOfMemoryError异常 由于书中所实例均为jdk1.6或jdk1.7,在jdk1.8中很多vm参数都被移除,这里就不赘述,发生上述异常,基本都是创建了太多的对象,导致内存不足,然后溢出。 对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收。 如果这次回收还没有足够的内存,才会抛出内存溢出异常

    17920

    绝了!华为技术专家居然把JVM内存模型讲解这么细致!

    每个线程在创建后,都会产生自己的程序计数器和栈帧,程序计数器用来存放执行指令的偏移量和行号指示器等,线程执行或恢复都要依赖程序计数器。程序计数器在各个线程之间互不影响,此区域也不会发生内存溢出异常。 Java虚拟机栈会出现两种异常: StackOverFlowError 若Java虚拟机栈的内存大小不允许动态扩展,那么当线程请求的栈深度大于虚拟机允许的最大深度时(但内存空间可能还有很多),就抛出异常 ,此时抛出OutOfMemoryError异常 Java虚拟机栈也是线程私有的,每个线程都有各自的Java虚拟机栈,而且随着线程的创建而创建,随线程的死亡而死亡。 堆内存物理上不一定要连续,只需要逻辑连续即可,就像磁盘空间一样. 堆是垃圾回收的主要区域,所以也被称为GC堆. 关闭钩子本质是一个线程(也称为hock线程),可以通过Runtime的addshutdownhock (Thread hock)向jvm注册一个关闭钩子。

    36241

    Java虚拟机内存初探

    Register) Java虚拟机栈(VM Stack) 本地方法栈(Native Method Stack) 方法区(method area) 堆(heap) 一、程序计数器 用来指示程序执行哪一条指令,跟汇编语言的程序计数器的功能在逻辑是一样的 在Java虚拟机规范中,对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展 ,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。 与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。 五、方法区 方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、以及编译器编译后的代码等。

    23120

    JVM内存区域认识

    因此,线程为了切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,各条线程之间互不影响,独立存储。故称该内存区域为“线程私有”的内存。 在虚拟机规范中,对虚拟机栈定义了两种异常状况: 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常 如果虚拟机可以动态扩展(当前大部分虚拟机都可动态扩展,只不过虚拟机规范中允许固定长度的虚拟机栈 ,只要逻辑是连续的即可,就像我们的磁盘空间一样;在实现时,既可以实现成固定大小的,也可以是可扩展的(通过-Xmx和-Xms控制) 如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError ,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常 运行时常量池(RunTime Constant Pool) 运行时常量池是方法区的一部分。 这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。

    3830

    探究JVM——运行时数据区

    StackOverflow:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常 OOM:如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展,只不过 与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。 OOM:如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常区域的内存回收目标主要是针对常量池的回收和对类型的卸载,一般来说,这个区域的回收“成绩”比较难以令人满意,尤其是类型的卸载,条件相当苛刻,但是这部分区域的回收确实是必要的。 OOM:根据Java虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常

    45370

    Java虚拟机运行时数据区域

    经常有人把Java内存区分为堆内存(Heap)和栈内存(Stack),这种分法比较粗糙,Java内存区域的划分实际远比复杂。 在Java虚拟机规范中,对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展 与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。 如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常区域的内存回收目标主要是针对常量池的回收和对类型的卸载,一般来说,这个区域的回收“成绩”比较难以令人满意,尤其是类型的卸载,条件相当苛刻,但是这部分区域的回收确实是必要的。

    13121

    jvm内存结构

    4)方法出口等 方法从调用到执行完成的过程,就对应了,一个栈帧在虚拟机栈中的入栈和出栈的过程 有两种异常: 如果线程请求的栈深度大于JVM所允许的深度,将抛出StackOverflowError异常 如果栈扩展时无法申请到足够的内存 虚拟机和本地方法栈溢出 由于在HotSpot虚拟机中并不区分虚拟机栈和本地方法栈,因此,对于HotSpot来说,虽然-Xoss参数(设置本地方法栈大小)存在,但实际是无效的,栈容量由-Xss参数设定 关于虚拟机栈和本地方法栈,在Java虚拟机规划中描述了两种异常: 如果线程请求的栈深度大于虚拟机所允许的最大尝试,将抛出抛出StackOverflowError异常 如果虚拟机在扩展栈时无法申请到足够的内存空间 (最后程序还是会停止的) 在单线程下,无论是由于栈帧太大还是虚拟机容量太小,当内存无法分配时,虚拟机都是抛出StackOverflowError异常。    * 由于在Windows平台的虚拟机中,Java的线程是映射到操作系统的内核线程的, * 因此上述代码执行时有较大的风险,可能会导致操作系统假死。

    8420

    JVM老生常谈之运行时数据区

    异常情况 如果线程请求的栈深度大于虚拟机所允许的深度,就会抛出StackOverflowError异常 如果虚拟机可以动态扩展(当前大部分的Java虚拟机都可动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机 本地方法栈也会抛出StackOverflowError和OutOfMemoryError异常。 程序计数器还存储了当前正在运行的流程,包括正在执行的指令、跳转、分支、循环、异常处理等。 堆 堆是线程共享的一块内存区域。 那一个对象创建的时候,到底是在堆上分配,还是在栈分配呢?和两个方面有关:对象的类型和在 Java 类中存在的位置。 Java 的对象可以分为基本数据类型和普通对象。 异常 当常量池无法再申请到内存时会抛出OutOfMemoryError异常。 元空间 在 Java 8 之前,类的信息是放在一个叫 Perm 区的内存里面的。

    86120

    扫码关注云+社区

    领取腾讯云代金券