精华内容
下载资源
问答
  • 本地方法栈和Java虚拟机发挥的作用非常相似,主要区别是Java虚拟机执行的是Java方法服务,而本地方法栈执行Native方法服务(通常用C编写)。 有些虚拟机发行版本(譬如Sun HotSpot虚拟机)直接将本地方法栈和Java...

    本地方法栈和Java虚拟机栈发挥的作用非常相似,主要区别是Java虚拟机栈执行的是Java方法服务,而本地方法栈执行Native方法服务(通常用C编写)。

    有些虚拟机发行版本(譬如Sun HotSpot虚拟机)直接将本地方法栈和Java虚拟机栈合二为一。与虚拟机栈一样,本地方法栈也会抛出StackOverflowError和OutOfMemoryError异常。

    对于一个运行中的Java程序而言,它还可能会用到一些跟本地方法相关的数据区。当某个线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的世界。本地方法可以通过本地方法接口来访问虚拟机的运行时数据区,但不止如此,它还可以做任何它想做的事情。

    本地方法本质上时依赖于实现的,虚拟机实现的设计者们可以自由地决定使用怎样的机制来让Java程序调用本地方法。

    任何本地方法接口都会使用某种本地方法栈。当线程调用Java方法时,虚拟机会创建一个新的栈帧并压入Java栈。然而当它调用的是本地方法时,虚拟机会保持Java栈不变,不再在线程的Java栈中压入新的帧,虚拟机只是简单地动态连接并直接调用指定的本地方法。

    如果某个虚拟机实现的本地方法接口是使用C连接模型的话,那么它的本地方法栈就是C栈。当C程序调用一个C函数时,其栈操作都是确定的。传递给该函数的参数以某个确定的顺序压入栈,它的返回值也以确定的方式传回调用者。同样,这就是虚拟机实现中本地方法栈的行为。

    很可能本地方法接口需要回调Java虚拟机中的Java方法,在这种情况下,该线程会保存本地方法栈的状态并进入到另一个Java栈。

    下图描绘了这样一个情景,就是当一个线程调用一个本地方法时,本地方法又回调虚拟机中的另一个Java方法。

    这幅图展示了JAVA虚拟机内部线程运行的全景图。一个线程可能在整个生命周期中都执行Java方法,操作它的Java栈;或者它可能毫无障碍地在Java栈和本地方法栈之间跳转。 
      在这里插入图片描述

    该线程首先调用了两个Java方法,而第二个Java方法又调用了一个本地方法,这样导致虚拟机使用了一个本地方法栈。假设这是一个C语言栈,其间有两个C函数,第一个C函数被第二个Java方法当做本地方法调用,而这个C函数又调用了第二个C函数。之后第二个C函数又通过本地方法接口回调了一个Java方法(第三个Java方法),最终这个Java方法又调用了一个Java方法(它成为图中的当前方法)。

    展开全文
  • 而 JAVA 内存模型是从主内存和线程私有内存角度的描述。从以下两张图可以看出:​ JAVA内存模型​ JVM内存模型Java虚拟机总共由三大模块组成:类加载器子系统运行时数据区执行引擎本篇我们介绍第二大模块——运行时...

    前言

    在正式学习 JVM 内存模型之前,先注意以下几个是问题:

    JVM 内存模型与 JAVA 内存模型不是同一个概念。JVM 内存模型是从运行时数据区的结构的角度描述的概念;而 JAVA 内存模型是从主内存和线程私有内存角度的描述。从以下两张图可以看出:

    ​ JAVA内存模型

    ​ JVM内存模型

    Java虚拟机总共由三大模块组成:类加载器子系统运行时数据区执行引擎本篇我们介绍第二大模块——运行时数据区(JVM内存模型)。

    其实虚拟机的这些模块并不是独立的,都是相互联系的。java 文件编译为 class 文件,通过类加载子系统加载,信息再到 JVM 托管的内存中(部分操作会与本地内存交互)的流转,再到垃圾回收等等,都是一系列的操作。

    概览

    运行时数据区分为几大模块(如上图所示):

    线程共享区:

    JAVA堆

    方法区

    线程私有区:

    JAVA栈

    本地方法栈

    程序计数器

    本文中,我们将从以下几个方法面来分析各个区域:

    功能

    存储的内容

    是否有内存溢出和内存泄露

    是否进行垃圾回收

    对应的垃圾回收算法

    垃圾回收流程

    性能调优

    线程私有区

    程序计数器

    程序计数器是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。字节码解释器工作时通过该计数器的值来选择选取下一条需要执行的字节码的指令,分支、循环、跳转、异常处理、线程恢复都需要依赖该区域。

    通俗点讲,该区域存放的就是一个指针,指向方法区的方法字节码,用来存储指向下一条指令的地址,也就是即将要执行的指令代码。

    如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Native方法,这个计数器值则为空(Undefined)。

    当执行完一行指令码,JVM执行引擎会更新程序计数器的值。

    由于Java 虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。(方法的调用,方法中又调用另外一个方法,正式满足栈的“先进先出,后进后出”的模型)。

    OutOfMemoryError:无

    虚拟机栈

    它描述的是java方法执行的内存模型,其生命周期与线程相同。

    每个方法在执行的同时都会创建一个栈帧(StackFrame),每一个栈帧又包括局部变量表、操作数栈、动态链接、方法出口等。方法的调用,方法中又调用另外一个方法,正式满足栈的“先进先出,后进后出”的模型。即每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

    以上都只是几个很机械的概念,难以深入理解。下面我通过一个示例,来分析虚拟机栈的存储内容。

    首先创建一个简单的程序:

    package com.sunwin.robotcloud.test;

    /**

    * Created by追梦1819on2019-11-01.

    */

    publicclass CalculateMain {

    publicintcalculate(){

    inta = 3;

    intb=4;

    intc = a+b;

    returnc;

    }

    publicstaticvoid main(String[] args) {

    CalculateMain main = new CalculateMain();

    intd = main.calculate();

    System.out.println(d);

    }

    对于以上程序,线程启动时,虚拟机会给主线程 main 分配一个大的内存空间,然后给main方法分配一个栈帧,存放该方法的局部变量;

    执行calculate()方法时又分配一个calculate()的栈帧,存放对应方法的局部变量。

    要注意的是,一个方法分配一个单独的内存区域,即栈帧。

    Java 属于高级语言,难以直接通过代码看出它的执行过程。我们通过底层的字节码,反解析出执行的指令码,来分析底层执行过程。

    进入 CalculateMain.class 文件目录,执行命令:

    将指令码直接输出到文件 CalculateMain.txt:

    Compiledfrom"CalculateMain.java"

    publicclass com.sunwin.robotcloud.test.CalculateMain {

    publiccom.sunwin.robotcloud.test.CalculateMain();

    Code:

    0: aload_0

    1: invokespecial #1 // Method java/lang/Object."":()V

    4: return

    publicintcalculate();

    Code:

    0: iconst_3

    1: istore_1

    2: iconst_4

    3: istore_2

    4: iload_1

    5: iload_2

    6: iadd

    7: istore_3

    8: iload_3

    9: ireturn

    publicstaticvoid main(java.lang.String[]);

    Code:

    0: new #2 // class com/sunwin/robotcloud/test/CalculateMain

    3: dup

    4: invokespecial #3 // Method "":()V

    7: astore_1

    8: aload_1

    9: invokevirtual #4 // Method calculate:()I

    12: istore_2

    13: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;

    16: iload_2

    17: invokevirtual #6 // Method java/io/PrintStream.println:(I)V

    20: return

    }

    先看看calculate()方法,根据以上指令,查询JVM指令手册,可以得到以上程序的执行流程:

    0.将int类型常量3压入(操作数)栈;

    1.将int类型值3存入局部变量1(1是数组下标),也就是在局部变量表中给a分配一块内存(用以存储3);

    2.将int类型常量4压入(操作数)栈;

    3.将int类型值4存入局部变量2;

    4.从局部变量1中装载int类型值,也就是将局部变量表的值3,拿出来加载到操作数栈;

    5.从局部变量2中装载int类型值;

    6.两值相加;

    7.(将数存入到操作数栈?)将int类型值7存入局部变量3;

    8.从局部变量3中装载int类型值;

    9.返回计算值。

    以上是方法执行时的局部变量在内存中的流转过程。总结就是:

    操作数栈相当于数据在操作时的临时中转站

    局部变量表:局部变量存放空间。是一个字长为单位、从0开始计数的数组。类型为int、float、reference、retrueAddress的值,只占据一项。类型为byte、short、char的值存入数组前都被转化为int值。类型为long、double的值在其中占据连续的两项。索引指向第一个值即可。

    不过需要注意的是,虚拟机对byte、short、char是直接支持的,只不过在局部变量表和操作数栈中是被转化为了int值,在堆和方法区中,依然是原来的类型。

    操作数栈:数据操作的临时空间。与局部变量表类似。唯一不同的是,它并非是通过索引来访问的,而是通过压栈和出栈来访问的。

    动态链接:存放的是方法的jvm指令码的内存地址,运行时动态生成的。

    对象有对象头,其中一个类型指针指向方法区的类元信息

    方法出口:存放的是出该方法,进入下一个方法的程序计数器的值。

    JAVA栈结构

    异常情况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError 异常;如果虚拟机栈可以动态扩展(当前大部分的Java 虚拟机都可动态扩展,只不过Java 虚拟机规范中也允许固定长度的虚拟机栈),当扩展时无法申请到足够的内存时会抛出OutOfMemoryError 异常。

    本地方法栈

    本地方法栈其实与java虚拟机栈极其相似。唯一的区别就是java虚拟机栈是为java方法服务,本地方法栈是为本地方法服务,虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。

    也会抛出StackOverflowError和OutOfMemoryError异常。

    线程共享区

    方法区

    该区域是存储虚拟机加载的类信息(字段方法的字节码、部分方法的构造器)、常量、静态变量、编译后的代码信息等,类的所有字段和方法字节码。以及一些特殊方法如构造函数,接口的代码也在此定义。简而言之,所有定义的方法的信息都保存在该区域。静态变量+常量+类信息(构造方法/接口定义)+运行时常量池都存在。

    可不连续,可固定大小,可扩展,也可不选择垃圾回收器。垃圾回收存在在该区域,但是出现较少。

    方法区是一种定义,概念,而永久代或者元空间是一种实现机制。

    OutOfMemoryError:有

    运行时常量池

    Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。

    OutOfMemoryError:有

    JAVA堆

    堆是Java虚拟机所管理的内存中最大的一块,它唯一的功能就是存储对象实例。几乎所有的对象(包含常量池),都会在堆上分配内存。

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

    垃圾回收器的主要管理区域。

    该区域,从垃圾回收的角度看,又分为新生代和老年代,新生代又分为 伊甸区(Eden space)和幸存者区(Survivor pace) ,Survivor 区又分为Survivor From 区和 Survivor To 区。如下图所示:

    以上区域的大小分配是:

    新生代:堆的 1/3

    老年代:堆的 2/3

    Eden 区: 新生代的 8/10

    Survivor From 区:新生代的 1/10

    Survivor To区:新生代的 1/10

    如果是从内存分配的角度来看,可以划分多个线程私有的分配缓冲区。

    对于堆空间来说,本质都是存储对象实例。不过如何分区,都只是为了更好地分配和管理对象实例。关于堆空间对对象实例的管理和回收,在下一章节阐述。

    同时,物理上可以不连续,但是逻辑上必须是连续的。

    以下是JVM内存模型整体结构:

    对象回收流程

    下图摘自网络:

    所有的类都是在伊甸区被 new 出来的,等到 Eden 区满的时候,会触发 Minor GC,将不需要再被其他对象引用的对象进行销毁,将剩余的对象移动到 From Survivor 区,每触发一次 Minor GC,对象的分代年龄会+1(分代年龄是存放在对象头里面的),From Survivor 区满的时候, From Survivor 区触发 Minor GC,未被回收的对象,分代年龄会继续+1,会移至 to survior 区,此时Eden的未被回收的对象也是移至 To Survivor 区,To Survivor 区满的时候,被移至 From Survivor 区,以此类推。

    对象的分代年龄到15的时候,对象会进入到老年代(静态变量(对象类型)、数据库连接池等)。若老年代也满了,这个时候会产生 Major GC(Full GC),进行老年区的内存清理。若老年区执行了 Full GC之后发现依然无法进行对象的保存,就会产生OOM 异常 OutOfMemoryError。

    注意事项

    运行时数据区,版本不同,会有细微的差别,具体如下:元数据区:元数据区取代了永久代(jdk1.8以前),本质和永久代类似,都是对JVM规范中方法区的实现,区别在于元数据区并不在虚拟机中,而是使用本地物理内存,永久代在虚拟机中,永久代逻辑结构上属于堆,但是物理上不属于堆,堆大小=新生代+老年代。元数据区也有可能发生OutOfMemory异常;jdk1.6及以前:有永久代,常量池在方法区;jdk1.7:有永久代,但已经逐步“去永久代”,常量池在堆;jdk1.8及以后:无永久代,常量池在元空间(用的是计算机的直接内存,而不是虚拟机管理的内存)。

    为什么jdk1.8用元数据区取代了永久代?官方解释:移除永久代是为融合HotSpot JVM与JRockit VM而做出的努力,因为JRockit没有永久代,不需要配置永久代。(简单说,就是两者竞争,谁赢了就听谁的。)

    元数据区的动态扩展,默认–XX:MetaspaceSize值为21MB的高水位线。一旦触及则Full GC将被触发并卸载没有用的类(类对应的类加载器不再存活),然后高水位线将会重置。新的高水位线的值取决于GC后释放的元空间。如果释放的空间少,这个高水位线则上升。如果释放空间过多,则高水位线下降。

    【编辑推荐】

    【责任编辑:武晓燕 TEL:(010)68476606】

    点赞 0

    展开全文
  • 一、内存与线程内存:内存是非常重要的系统资源,是硬盘和cpu的中间仓库及桥梁,承载着操作系统和应用程序的实时运行。JVM内存布局规定了JAVA在运行过程中内存申请、分配、管理的策略,保证了JVM的高效稳定运行。...

    一、内存与线程

    内存:

    内存是非常重要的系统资源,是硬盘和cpu的中间仓库及桥梁,承载着操作系统和应用程序的实时运行。JVM内存布局规定了JAVA在运行过程中内存申请、分配、管理的策略,保证了JVM的高效稳定运行。不同的jvm对于内存的划分方式和管理机制存在着部分差异(对于Hotspot主要指方法区)

    java虚拟机定了了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁。另外一些则是与线程一一对应的,这些与线程对应的数据区域会随着线程开始和结束而创建和销毁。

    如图,灰色的区域为单独线程私有的,红色的为多个线程共享的,即

    每个线程:独立包括程序计数器、栈、本地栈

    线程间共享:堆、堆外内存(方法区、永久代或元空间、代码缓存)

    一般来说,jvm优化95%是优化堆区,5%优化的是方法区。

    线程:

    线程是一个程序里的运行单元,JVM允许一个程序有多个线程并行的执行;

    在HotSpot JVM,每个线程都与操作系统的本地线程直接映射。

    当一个java线程准备好执行以后,此时一个操作系统的本地线程也同时创建。java线程执行终止后。本地线程也会回收。

    操作系统负责所有线程的安排调度到任何一个可用的CPU上。一旦本地线程初始化成功,它就会调用java线程中的run()方法.

    查看jvm线程的方法:

    使用jconsole

    HotSpot JVM后台主要线程:

    虚拟机线程:这种线程的操作时需要JVM达到安全点才会出现。这些操作必须在不同的线程中发生的原因是他们都需要JVM达到安全点,这样堆才不会变化。这种线程的执行包括“stop-the-world”的垃圾收集,线程栈收集,线程挂起以及偏向锁撤销

    周期任务线程:这种线程是时间周期事件的提现(比如中断),他们一般用于周期性操作的调度执行。

    GC线程:这种线程对于JVM里不同种类的垃圾收集行为提供了支持

    编译线程:这种线程在运行时会降字节码编译成本地代码

    信号调度线程:这种线程接收信号并发送给JVM,在它内部通过调用适当的方法进行处理。

    二、运行时数据区概览

    Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为上图若干个不同的数据区域。这些区域都有各自的用途,已经创建和销毁时间,有的区域随着虚拟机进程的启动而创建,有些区域则依赖用户线程的启动和结束而创建和销毁。

    三、程序计数器(pc寄存器)

    介绍:JVM中的程序计数寄存器(Program Counter Register)中,Register的命名源于CPU的寄存器,寄存器存储指令相关的现场信息。CPU只有把数据装到寄存器才能够运行。JVM中的PC寄存器是对计算机PC寄存器的一种抽象模拟。

    作用:PC寄存器是用来存储指向下一条指令的地址,也即将将要执行的指令代码。由执行引擎读取下一条指令。

    它是一块很小的内存空间,几乎可以忽略不计。也是运行速度最快的存储区域

    在jvm规范中,每个线程都有它自己的程序计数器,是线程私有的,生命周期与线程的生命周期保持一致

    任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。程序计数器会存储当前线程正在执行的java方法的JVM指令地址;或者,如果实在执行native方法,则是未指定值(undefined)。

    它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成

    字节码解释器工作时就是通过改变这个计数器的值来选取吓一跳需要执行的字节码指令

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

    CPU时间片

    CPU时间片即CPU分配各各个程序的时间,每个线程被分配一个时间段。称作它的时间片。

    在宏观上:我们可以同时打开多个应用程序,每个程序并行不悖,同时运行。

    但在微观上:由于只有一个CPU,一次只能处理程序要求的一部分,如何处理公平,一种方法就是引入时间片,每个程序轮流执行。

    并行:同一时间多个线程同时执行;

    并发:一个核快速切换多个线程,让它们依次执行,看起来像并行,实际上是并发

    四、本地方法栈

    Java虚拟机栈用于管理Java方法的调用,而本地方法栈用于管理本地方法的调用

    本地方法栈,也是线程私有的。

    允许被实现成固定或者是可动态拓展的内存大小。(在内存溢出方面是相同的)

    如果线程请求分配的栈容量超过本地方法栈允许的最大容量,Java虚拟机将会抛出一个StackOverFlowError异常。

    如果本地方法栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的本地方法栈,那么java虚拟机将会抛出一个OutOfMemoryError异常。

    本地方法是使用C语言实现的

    它的具体做法是Native Method Stack中登记native方法,在Execution Engine执行时加载本地方法库。

    当某个线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的世界。它和虚拟机拥有同样的权限

    本地方法可以通过本地方法接口来 访问虚拟机内部的运行时数据区

    它甚至可以直接使用本地处理器中的寄存器

    直接从本地内存的堆中分配任意数量的内存

    并不是所有的JVM都支持本地方法。因为Java虚拟机规范并没有明确要求本地方法栈的使用语言、具体实现方式、数据结构等。如果JVM产品不打算支持native方法,也可以无需实现本地方法栈。

    在hotSpot JVM中,直接将本地方法栈和虚拟机栈合二为一。

    展开全文
  • JVM 运行时数据区域大致可以分为:程序计数器、虚拟机本地方法栈、堆区、元空间、运行时常量池、直接内存等区域;就是下面这个样子的:其中有些区域,随着 JDK 版本的升级不断调整,例如:JDK 1.6,字符串常量池...

    JVM 运行时数据区域大致可以分为:程序计数器、虚拟机栈、本地方法栈、堆区、元空间、运行时常量池、直接内存等区域;就是下面这个样子的:

    其中有些区域,随着 JDK 版本的升级不断调整,例如:JDK 1.6,字符串常量池位于永久代的运行时常量池中;

    JDK 1.7,字符串常量池从永久代剥离,放入了堆中;

    JDK 1.8,元空间取代了永久代,并且放入了本地内存(Native memory)中。

    以上几个区域,按照线程公有还是私有可分为:线程隔离:程序计数器、虚拟机栈、本地方法栈;

    线程公有:其它的都是线程共享的区域。

    线程私有

    1. 程序计数器

    一个 CPU 在某个时间点,只能做一件事情,在多线程的情况下,CPU 运行时间被划分成若干个时间片,分配给各个线程执行;

    程序计数器的作用就是记录当前线程执行的位置,当线程被切换回来的时候,能够找到该线程上次运行到哪儿了;所以程序计数器一定是线程隔离的。

    2. 虚拟机栈和本地方法栈虚拟机栈:每个 Java 方法在执行的同时,会创建一个栈帧,用于存储局部变量表、操作数栈、常量池引用等信息;方法的调用过程,就是一个栈帧在 Java 虚拟机栈中入栈和出栈的过程;

    本地方法栈:和虚拟机栈很类似,区别在于虚拟机栈为 Java 方法服务,本地方法栈为 Native 方法服务;其中 Native 方法可以看做用其它语言(C、C++ 或汇编语言等)编写的方法;

    HotSpot 虚拟机就选择了将虚拟机栈和本地方法栈合并在了一起;

    为了保证线程中的局部变量不被别的线程访问到,所以虚拟机栈和本地方法栈是线程隔离的。

    线程公有

    1. 堆区

    对于堆栈的区别总结一句话:堆中存对象,栈中存基本数据类型和堆中对象的引用;一个对象的大小是可以动态变化的,而引用是固定大小的。

    这么看就容易理解堆为什么是线程公有的了,省地儿啊。

    2. 元空间区/方法区

    方法区用于存放已被加载的类信息、常量、静态变量、即编译器编译后的代码等。

    还有要注意的一点:方法区是 JVM 的规范,在 JDK 1.8 之前,方法区的实现是永久代;从 JDK 1.8 开始 JVM 移除了永久代,使用本地内存来存储元数据并称之为:元空间(Metaspace)。

    3. 运行时常量池

    Class 文件中的常量池,会在类加载后被放入这个区域。

    另外在 JDK 1.7 之前,字符串常量池就在运行时常量池中,后来字符串常量池放入了堆中,而运行时常量池仍然在方法区(元空间区)中。

    有兴趣的朋友可以自己测试一下,以死循环方式创建字符串常量,在 JDK 1.6 里会报永久代 OOM ;在 JDK 1.7 里会报堆区 OOM 。

    4. 直接内存

    也叫做堆外内存,并不是虚拟机运行时数据区的一部分,也不是Java 虚拟机规范中定义的内存区域。

    JDK 1.4 加入的 NIO 类,引入了一种基于通道 ( Channel ) 与缓冲区 ( Buffer ) 的 I/O 方式,它可以使用 native 函数库直接分配堆外内存,然后通过堆上的DirectByteBuffer对象对这块内存进行引用和操作。

    简单来说,直接内存就是 JVM 内存之外有一块内存区域,我们通过堆上的一个对象可以操作它;具体等讲到 NIO 部分的时候,再回来加深理解。会点代码的大叔

    展开全文
  • 直接上图:从图中看到,JVM内存分为两个主要区域,一个是所有线程共享的数据区,一个是线程隔离数据区线程私有)线程隔离数据区程序计数器(ProgramCounterRegister):一小块内存空间,单前线程所执行的字节码行号指示...
  • 左边是线程共享的(方法区、堆),右边是线程私有的(虚拟机本地方法栈、计数器) 线程私有的生命周期都比较短 Method Area(方法区) 方法区是各个线程共享的内存区域,在虚拟机启动时创建。 用于存储已被虚拟机...
  • (一)java内存区域管理C/C++每一个new操作都需要自己去delete/free,而java里面有虚拟机自动管理...运行时区域主要分为:线程私有:程序计数器:Program Count Register,线程私有,没有垃圾回收虚拟机:VM Stack,线...
  • 来自:会点代码的大叔JVM 运行时数据区域大致可以分为:程序计数器、虚拟机本地方法栈、堆区、元空间、运行时常量池、直接内存等区域;就是下面这个样子的:其中有些区域,随着 JDK 版本...
  • 1,java内存模型简介《深入理解java虚拟机》里将java内存分为如下五个模块:堆-堆是所有线程共享的,主要...Java虚拟机/本地方法栈线程私有的,主要存放局部变量表,操作数,动态链接和方法出口等;pc寄存器...
  • 进程的公有数据(全局变量,函数里的静态变量) 进程打开的文件描述符 信号的处理器 进程的当前目录和进程用户ID与进程组ID。 进程拥有这许多共性的同时,还拥有自己的个性。有了这些个性,线程才能实现并发性...
  • java内存管理初见java虚拟机所管理的内存包括以下几个运行时数据区域:1.程序计数器(线程私有)指向当前执行的字节码。字节码解释器通过改变...2.java虚拟机(线程私有)描述的是java方法执行的内存模型:每个方法...
  • JVM内存区域划分

    2020-12-28 21:41:48
    线程公有 1.堆:存放对象实例堆是Java 虚拟机所管理的内存中最大的一块。Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存...
  • 什么是进程?进程是程序的⼀次执⾏过程,是系统运⾏程序的基本单位,因此进程是动态的。...与进程不同的是同类的多个线程共享进程的堆和⽅法区资源,但每个线程有⾃⼰的程序计数器、虚拟机本地⽅法,所以系统在产
  • 线程私有存储区(Thread-Private Storage)1.1 内存(Stack)1.1.1 虚拟机(VM Stack)1.1.2 本地方法栈(Native Method Stack)2 线程公有存储区(Thread-Public Storage)2.1 堆内存(Heap)2.1.1 新生代...
  • 线程公有 在运行时数据区中,方法区和堆是属于线程公有的,也就是这两块区域是“循环利用”的,所以要对其进行垃圾回收。其是在虚拟机启动时创建。 线程私有 虚拟机本地方法栈、程序计数器是属于线程私有的,...
  • 许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存、CPU、缓存等予以说明。实际上,在实际的Java开发工作中,...
  • (1)(stack):由编译器进行管理,自动分配和释放,存放函数调用过程中的各种参数、局部变量、返回值以及函数返回地址。操作方式类似数据结构中的。 (2)堆(heap):用于程序动态申请分配和释放空间。C语言...
  • Java内存模型即途中的Runtime Data ...私有部分为:程序计数器、虚拟机本地方法栈 程序计数器 代表当前线程所执行的字节码行号指示器(是逻辑计数器而不是物理计数器) 改变计数器的值来选取下一条需要执行...
  • JVM-内存区域划分

    2020-12-29 15:00:47
    线程公有 1.堆:存放对象实例 堆是Java 虚拟机所管理的内存中最大的一块。Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配...
  • 线程共享与私有

    2017-04-18 17:32:45
    线程共享的环境包括:进程代码段、进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通讯)、进程打开的文件描述符、信号的处理器、进程的当前目录和进程用户ID与进程组ID。  进程拥有这许多共性的...
  • JAVA的内存模型及结构

    2020-12-29 15:01:11
    原文链接译文链接作者:Tai Truong ...Java内存模型堆内存存放对象以及数组的数据,方法区存放类的信息(包括类名、方法、字段)、静态变量、编译器编译后的代码,本地区包含线程栈本地方法栈等存放线程方法区有时...
  • 文章目录一、什么是线程安全二、线程安全状态(等级)2.1不可变2.2绝对线程安全2.3相对线程安全2.4线程兼容2.5线程对立三、线程安全的实现方法3.1互斥同步(阻塞同步)(悲观并发)3.2非阻塞同步 (乐观并发)3.3无...
  • 如何确保线程安全

    千次阅读 2019-12-19 11:12:31
    在jvm的世界里,线程就像不相干的平行空间,串行在虚拟机中,那么java如何保证线程安全?说到线程安全,首先简单了解一下多线程: 多线程 充分利用CPU资源,为了提高CPU的使用率,采用多线程的方式去同时完成几件...
  • 同一进程下线程共享的数据和独有的数据
  • 详解 JVM 内存模型 JVM 内存模型主要指运行时的数据区,包括 5 个部分,如下图所示 ...本地方法栈类似,也是用来保存线程执行方法时的信息,不同的是,执行 Java 方法使用,而执行 native 方法使用本...
  • 面试题汇总二 Java 多线程篇 面试题汇总三 Java 集合篇 面试题汇总四 JVM 篇 面试题汇总五 Spring 篇 面试题汇总六 数据库篇 面试题汇总七 计算机网络篇 目录 前言 多线程 开启线程的三种方式? 什么是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,377
精华内容 2,550
关键字:

本地方法栈线程公有