JAVA虚拟机(JVM jvm 内存模型) 完整流程图
JVM 最完整深入解析

JVM最完整深入解析Java虚拟机在执行Java程序的过程中会将其管理的内存划分为若干个不同的数据区域,这些区域有各自的用途、创建和销毁的时间,有些区域随虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束来建立和销毁。
Java虚拟机所管理的内存包括以下几个运行时数据区域,如图:1、程序计数器:指向当前线程正在执行的字节码指令。
线程私有的。
2、虚拟机栈:虚拟机栈是Java执行方法的内存模型。
每个方法被执行的时候,都会创建一个栈帧,把栈帧压人栈,当方法正常返回或者抛出未捕获的异常时,栈帧就会出栈。
(1)栈帧:栈帧存储方法的相关信息,包含局部变量数表、返回值、操作数栈、动态链接a、局部变量表:包含了方法执行过程中的所有变量。
局部变量数组所需要的空间在编译期间完成分配,在方法运行期间不会改变局部变量数组的大小。
b、返回值:如果有返回值的话,压入调用者栈帧中的操作数栈中,并且把PC的值指向方法调用指令后面的一条指令地址。
c、操作数栈:操作变量的内存模型。
操作数栈的最大深度在编译的时候已经确定(写入方法区code属性的max_stacks项中)。
操作数栈的的元素可以是任意Java类型,包括long和double,32位数据占用栈空间为1,64位数据占用2。
方法刚开始执行的时候,栈是空的,当方法执行过程中,各种字节码指令往栈中存取数据。
d、动态链接:每个栈帧都持有在运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态链接。
(2)线程私有3、本地方法栈:(1)调用本地native的内存模型(2)线程独享。
4、方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据(1)线程共享的(2)运行时常量池:A、是方法区的一部分B、存放编译期生成的各种字面量和符号引用C、Class文件中除了存有类的版本、字段、方法、接口等描述信息,还有一项是常量池,存有这个类的编译期生成的各种字面量和符号引用,这部分内容将在类加载后,存放到方法区的运行时常量池中。
java内存管理之内存模型

java内存管理之内存模型1,运⾏时数据区域1. 程序计数器(program counter register)2. Java虚拟机栈(jvm stack)3. 本地⽅法栈(native method stack)4. java堆(heap)5. ⽅法区(method area)6. 运⾏时常量池7. 直接内存1. 程序计数器(program counter register)1.1 概念 程序计数器是⼀块较⼩的内存空间,可以把它看作当前线程正在执⾏的字节码的⾏号指⽰器。
也就是说,程序计数器⾥⾯记录的是当前线程正在执⾏的那⼀条字节码指令的地址。
注:如果当前线程正在执⾏的是⼀个本地⽅法,那么此时程序计数器为空。
(这⾥的本地⽅法即⾮java语⾔编写的⽅法)。
1.2 作⽤1)字节码解释器通过改变程序计数器来依次读取指令,从⽽实现代码的流程控制,如:顺序执⾏、选择、循环、异常处理。
2)在多线程的情况下,程序计数器⽤于记录当前线程执⾏的位置,从⽽当线程被切换回来的时候能够知道该线程上次运⾏到哪⼉了。
1.3 特点1)线程私有。
每条线程都有⼀个程序计数器。
2)是唯⼀不会出现OutOfMemoryError的内存区域。
(ng.OutOfMemoryError内存溢出,即说明jvm的内存不够⽤了)3)⽣命周期随着线程的创建⽽创建,随着线程的结束⽽死亡。
2. Java虚拟机栈(jvm stack)2.1 概念 Java虚拟机栈是描述Java⽅法运⾏过程的内存模型。
Java虚拟机栈会为每⼀个即将运⾏的Java⽅法创建⼀块叫做“栈帧”的区域,这块区域⽤于存储该⽅法在运⾏过程中所需要的⼀些信息,这些信息包括: 1)局部变量表(基本数据类型、引⽤类型、returnAddress类型的变量(此变量为JVM原始数据类型,在java语⾔中不存在对应类型)) 2)操作数栈 3)动态链接 4)⽅法出⼝信息等当⽅法在运⾏过程中需要创建局部变量时,就将局部变量的值存⼊栈帧的局部变量表中。
深入理解java虚拟机

深入理解java虚拟机(一)虚拟机内存划分Java虚拟机在执行Java程序时,会把它管理的内存划分为若干个不同的数据区。
这些区域有不同的特性,起不同的作用。
它们有各自的创建时间,销毁时间。
有的区域随着进程的启动而创建,随着进程结束而销毁,有的则始终贯穿虚拟机整个生命周期。
Java虚拟机运行时内存区域主要分为七部分,分别是:程序计数器,Java虚拟机栈,本地方法栈,方法区,Java堆,运行时常量池,直接内存。
如上图所示(图片来源于网络):蓝色区域包裹的部分为运行时几个数据区域:白色的部分为线程私有的,既随着线程的启动而创建。
每个线程都拥有各自的一份内存区域。
它们是:JAVA栈(JAVA STACK),本地方法栈(NATIVE METHOD STACK),和程序计数器(PROGRAM COUNTER REGISTER)。
黄色部分是线程共享的,所有的线程共享该区域的内容。
他们是:方法区(METHOD AREA),堆(HEAP)。
我们分别来介绍这些区域。
(1)程序计数器(program counter register)学过计算机组成原理的都知道计算机处理器中的程序计数器。
当处理器执行一条指令时,首先需要根据PC中存放的指令地址,将指令由内存取到指令寄存器中,此过程称为“取指令”。
与此同时,PC中的地址或自动加1或由转移指针给出下一条指令的地址。
此后经过分析指令,执行指令。
完成第一条指令的执行,而后根据PC取出第二条指令的地址,如此循环,执行每一条指令。
处理器的程序计数器是指寄存器,而java程序计数器是指一小块内存空间。
java代码编译字节码之后,虚拟机会一行一行的解释字节码,并翻印成本地代码。
这个程序计数器盛放的就是当前线程所执行字节码的行号的指示器。
在虚拟机概念模型中,字节码解释器工作室就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支,循环,跳转,异常处理等都依赖于它。
Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式实现的,因此为了线程切换后还能恢复执行位置,每条线程都需要一个独立的程序计数器。
JVM内存区域(Java内存区域)、JVM垃圾回收机制(GC)初探

JVM内存区域(Java内存区域)、JVM垃圾回收机制(GC)初探⼀、JVM内存区域(Java内存区域) ⾸先区分⼀下JVM内存区域(Java内存区域)和Java内存模型(JMM)的概念。
Java线程之间的通信采⽤的是共享内存模型,这⾥提到的共享内存模型指的就是Java内存模型(简称JMM),Java内存模型(即Java Memory Model,简称JMM)本⾝是⼀种抽象的概念,并不真实存在;Java线程之间的通信由JMM控制,JMM决定⼀个线程对共享变量的写⼊何时对另⼀个线程可见。
⽽JVM内存区域,有的地⽅也称之为Java内存区域,是JVM对JMM的实现。
在JVM内部,Java内存模型把内存分成了两部分:线程栈区和堆区,也可以理解为线程共享内存区和线程私有内存区。
接下来就具体介绍分析⼀下JVM内存区域。
Java程序是交由JVM执⾏的,所以我们在谈Java内存区域划分的时候事实上是指JVM内存区域划分。
在讨论JVM内存区域划分之前,先来看⼀下Java程序具体执⾏的过程: 从图中可以看到,JVM主要由三⼤部分组成:类加载器、执⾏引擎、运⾏时数据区。
本篇博客主要介绍运⾏时数据区部分,类加载器会后续单独在⼀篇博客中介绍。
如上图所⽰,⾸先Java源代码⽂件(.java后缀)会被Java编译器编译为字节码⽂件(.class后缀),然后由JVM中的类加载器中的defineClass()⽅法加载各个类的字节码⽂件进jvm内存中,⽣成ng.Class对象,每个类在JVM中都拥有⼀个对应的ng.Class 对象,并存放于运⾏时数据区(Runtime Data Area)的堆中,它提供了类结构信息的描述。
数组、枚举及基本Java类型(如int、double等)甚⾄void都拥有对应的Class对象。
这也就是我们常说的Java类的静态加载,即程序在运⾏时,所需要的类就必须加载好,如果编译时这个类的.class⽂件不存在,程序将编译出错⽆法运⾏;还有⼀种是动态加载是通过反射机制在运⾏时⽤Class.forName()加载字节码⽂件获得ng.Class对象并放到JVM内存中。
jvm-gc

JVM的相关知识是学习java高级特性必须要去深入学习的。
平时也有一些学习和实践,不过总结比较少。
今天有时间总结一下最基础的内存模型和GC策略的知识,在此记录一下。
hotspot jvm内存模型1.内存模型hotspot的内存模型很多地方都有类似总结,我也简单总结了一下,大概可以用下图表示:关于几个分区的描述定义1.线程栈:线程创建是会为每个线程创建一个线程栈,线程栈里面会为每个方法调用创建一个栈帧。
主要用于保存线程的当前运行状态。
2.堆:用于存放运行时中生成的新对像。
会划分成新生代和老年代。
新生代里面又划分成了eden区、存活1区和存活2区。
3.永久区:方法和常量区,用于存放方法字节码元数据和各种常量。
为什么堆会划分为新生代和老年代?基本原理:对于大部分应用,常驻对象不多。
因为大部分存活寿命不长,新生代和老年代的划分有利于区分对待和缩小垃圾回收范围。
(Most allocated objects are not referenced (considered live) for long, that is, they die young. Few references from older to younger objects exist.)2.内存相关启动参数内存相关常见jvm参数参数含义-Xms 最小堆空间-Xmx 最大堆空间-Xmn 新生代空间-Xss 线程栈空间-XX:PermSize=xxx 永久代空间-XX:MaxPermSize=xxx 最大永久代空间-XX:SurviorRatio=xxx 代表eden:s0的比例-XX:NewRatio=xx 新生代和旧生代的比例.-XX:MaxTenuringThreshold。
在新生代最大存活次数hotspot 内存垃圾回收策略总结1.内存回收策略和常见概念常见内存回收策略可以从以下几个维度来理解:1.1 串行&并行串行:单线程执行内存回收工作。
java内存模型及GC原理 和 图解JVM在内存中申请对象及垃圾回收流程 - 小鸥的博客 - 博客频道 - CSDN

Collector一般使用一个称为堆的内存池来进行内存的分配和回收。
/zhaoxu0312/article/details/7225277
项目管理 (66)
项目投标 (2) system design&架构基础 (152) jdbc (3) Amazon (4) it时事 (8) nosql (50)
GC性能指标 Throughput: 程序时间(不包含GC时间)/总时间。 GC overhead: GC时间/总时间。 Pause time: GC运行时程序挂起时间。 Frequency of GC: GC频率。
flex (35) Python (37)
良好的扩展性,内存分配和GC在多核机器上不应该成为性能瓶颈。
eclipse plugin (48)
SWT&JFace (30) Web相关 (75) JSON (7) 数据仓库&数据挖掘 (92)
设计或选择Collector 串行或并行。 串行Collector在多核上也只有一个线程在运行,并行Collector可以同时有多个线程执行GC,但是
数据,或者合并一些数据减少内存的使用.如果还是不行那就加机器,加内存. 总结:在不影响功能的情况下,缓存对象越小越要,命中率越高越好.低命中率的缓存对象还不如
不缓存. 2,没使用缓存的情况,貌似不会出现full gc的情况,除非内存太小,或者设置不对,程序有漏洞.
java内存管理以及GC (强烈推荐)
文章分类
造成full gc的原因: new了很多对象,没有即时在主动释放掉>Eden内存不够用>不断把对象往old迁移>old满了>full
jvm系列(二):JVM内存结构

从更高的一个维度再次来看JVM和系统调用之间的关系 方法区和对是所有线程共享的内存区域;而java栈、本地方法栈和程序员计 用户登录 代码改变世界 密码登录 短信登录 忘记登录用户名 忘记密码 记住我 登录 第三方登录/注册 没有账户, 立即注册
jvm系列(二): JVM内存结构
JVM内存结构
所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块 区域?该怎么解决呢?其实如果你经常解决服务器性能问题,那么这些问题就会变的非常常见,了解JVM内存也是为了服务器出现性能问 题的时候可以快速的了解那块的内存区域出现问题,以便于快速的解决生产故障。
根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在 实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。
如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。
在通过一张图来了解如何通过参数来控制各区域的内存大小
控制参数 -Xms设置堆的最小空间大小。 -Xmx设置堆的最大空间大小。 -XX:NewSize设置新生代最小空间大小。 -XX:MaxNewSize设置新生代最大空间大小。 -XX:PermSize设置永久代最小空间大小。 -XX:MaxPermSize设置永久代最大空间大小。 -Xss设置每个线程的堆栈大小。
深入理解JVM-内存模型(jmm)和GC

深⼊理解JVM-内存模型(jmm)和GC1.Java内存区域Java程序内存的分配是在JVM虚拟机内存分配机制下完成。
Java内存模型(Java Memory其中⽅法区和堆是所有线程共享的,栈,本地⽅法栈和程序虚拟机则为线程私有的。
Model ,JMM)就是⼀种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能保证效果⼀致的机制及规范2.1 五⼤内存区域2.1.1 程序计数器程序计数器是⼀块很⼩的内存空间,它是线程私有的,可以认作为当前线程的⾏号指⽰器。
为什么需要程序计数器我们知道对于⼀个处理器(如果是多核cpu那就是⼀核),在⼀个确定的时刻都只会执⾏⼀条线程中的指令,⼀条线程中有多个指令,为了线程切换可以恢复到正确执⾏位置,每个线程都需有独⽴的⼀个程序计数器,不同线程之间的程序计数器互不影响,独⽴存储。
注意:如果线程执⾏的是个java⽅法,那么计数器记录虚拟机字节码指令的地址。
如果为native【底层⽅法】,那么计数器为空。
这块内存区域是虚拟机规范中唯⼀没有OutOfMemoryError的区域。
2.1.2 Java栈(虚拟机栈)同计数器也为线程私有,⽣命周期与相同,就是我们平时说的栈,栈描述的是Java⽅法执⾏的内存模型。
每个⽅法被执⾏的时候都会创建⼀个栈帧⽤于存储局部变量表,操作栈,动态链接,⽅法出⼝等信息。
每⼀个⽅法被调⽤的过程就对应⼀个栈帧在虚拟机栈中从⼊栈到出栈的过程。
【栈先进后出,下图栈1先进最后出来】对于栈帧的解释参考栈帧: 是⽤来存储数据和部分过程结果的数据结构。
栈帧的位置: 内存 -> 运⾏时数据区 -> 某个线程对应的虚拟机栈 -> here[在这⾥]栈帧⼤⼩确定时间: 编译期确定,不受运⾏期数据影响。
通常有⼈将java内存区分为栈和堆,实际上java内存⽐这复杂,这么区分可能是因为我们最关注,与对象内存分配关系最密切的是这两个。
java虚拟机学习

Java虚拟机学习(1):体系结构内存模型2016/11/02 | 分类:技术架构 | 0 条评论 | 标签: JVM分享到:8原文出处:java2000_wl一:Java技术体系模块图二:JVM内存区域模型1.方法区也称”永久代”、“非堆”,它用于存储虚拟机加载的类信息、常量、静态变量、是各个线程共享的内存区域。
默认最小值为16MB,最大值为64MB,可以通过-XX:PermSize 和-XX:MaxPermSize 参数限制方法区的大小。
运行时常量池:是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种符号引用,这部分内容将在类加载后放到方法区的运行时常量池中。
2.虚拟机栈描述的是Java 方法执行的内存模型:每个方法被执行的时候都会创建一个“栈帧”用于存储局部变量表(包括参数)、操作栈、方法出口等信息。
每个方法被调用到执行完的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
声明周期与线程相同,是线程私有的。
局部变量表存放了编译器可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(引用指针,并非对象本身),其中64位长度的long和double 类型的数据会占用2个局部变量的空间,其余数据类型只占1个。
局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量是完全确定的,在运行期间栈帧不会改变局部变量表的大小空间。
3.本地方法栈与虚拟机栈基本类似,区别在于虚拟机栈为虚拟机执行的java方法服务,而本地方法栈则是为Native方法服务。
4.堆也叫做java 堆、GC堆是java虚拟机所管理的内存中最大的一块内存区域,也是被各个线程共享的内存区域,在JVM启动时创建。
该内存区域存放了对象实例及数组(所有new的对象)。
图解JVM垃圾内存回收算法

图解JVM垃圾内存回收算法图解JVM垃圾内存回收算法这篇⽂章主要介绍了图解JVM垃圾内存回收算法,由于年轻代堆空间的垃圾回收会很频繁,因此其垃圾回收算法会更加重视回收效率,下⾯博主和⼤家来⼀起学习⼀下吧前⾔⾸先,我们要讲的是JVM的垃圾回收机制,我默认准备阅读本篇的⼈都知道以下两点:JVM是做什么的Java堆是什么因为我们即将要讲的就是发⽣在JVM的Java堆上的垃圾回收,为了突出核⼼,其他的⼀些与本篇不太相关的东西我就⼀笔略过了众所周知,Java堆上保存着对象的实例,⽽Java堆的⼤⼩是有限的,所以我们只能把⼀些已经⽤完的,⽆法再使⽤的垃圾对象从内存中释放掉,就像JVM帮助我们⼿动在代码中添加⼀条类似于C++的free语句的⾏为然⽽这些垃圾对象是怎么回收的,现在不知道没关系,我们马上就会讲到怎么判断对象为垃圾对象在了解具体的GC(垃圾回收)算法之前,我们先来了解⼀下JVM是怎么判断⼀个对象是垃圾对象的顾名思义,垃圾对象,就是没有价值的对象,⽤更严谨的语句来说,就是没有被访问的对象,也就是说没有被其他对象引⽤,这就牵引出我们的第⼀个判断⽅案:引⽤计数法引⽤计数法这种算法的原理是,每有⼀个其他对象产⽣对A对象的引⽤,则A对象的引⽤计数值就+1,反之,每有⼀个对象对A对象的引⽤失效的时候,A对象的引⽤计数值就-1,当A对象的引⽤计数值为0的时候,其就被标明为垃圾对象这种算法看起来很美好,了解C++的应该知道,C++的智能指针也有类似的引⽤计数,但是在这种看起来“简单”的⽅法,并不能⽤来判断⼀个对象为垃圾对象,我们来看以下场景:在这个场景中,A对象有B对象的引⽤,B对象也有A对象的引⽤,所以这两个对象的引⽤计数值均不为0,但是,A、B两个对象明明就没有任何外部的对象引⽤,就像⼤海上两个紧挨着的孤岛,即使他们彼此依靠着,但仍然是孤岛,其他⼈过不去,⽽且由于引⽤计数不为0,也⽆法判断为垃圾对象,如果JVM中存在着⼤量的这样的垃圾对象,最终就会频繁抛出OOM异常,导致系统频繁崩溃总⽽⾔之,如果有⼈问你为什么JVM不采⽤引⽤计数法来判断垃圾对象,只需要记住这⼀句话:引⽤计数法⽆法解决对象循环依赖的问题可达性分析法引⽤计数法已经很接近结果了,但是其问题是,为什么每有⼀个对象来引⽤就要给引⽤计数值+1,就好像有⼈来敲门就开⼀样,我们应该只给那些我们认识的、重要的⼈开门,也就是说,只有重要的对象来引⽤时,才给引⽤计数值+1但是这样还不⾏,因为重要的对象来引⽤只要有⼀个就够了,并不需要每有⼀个引⽤就+1,所以我们可以将引⽤计数法优化为以下形式:给对象设置⼀个标记,每有⼀个“重要的对象”来引⽤时,就将这个标记设为true,当没有任何“重要的对象”引⽤时,就将标记设为false,标记为false的对象为垃圾对象这就是可达性分析法的雏形,我们可以继续进⾏修正,我们并不需要主动标记对象,⽽只需要等待垃圾回收时找到这些“重要的对象”,然后从它们出发,把我们能找到的对象都标记为⾮垃圾对象,其余的⾃然就是垃圾对象我们将上⽂提到的“重要的对象”命名为GC Roots,这样就得到了最终的可达性分析算法的概念:创建垃圾回收时的根节点,称为GC Roots,从GC Roots出发,不能到达的对象就被标记为垃圾对象其中,可以作为GC Roots的区域有:虚拟机栈的栈帧中的局部变量表⽅法区的类属性和常量所引⽤的对象本地⽅法栈中引⽤的对象换句话说,GC Roots就是⽅法中的局部变量、类属性,以及常量垃圾回收算法终于到本⽂的重点了,我们刚刚分析了如何判断⼀个对象属于垃圾对象,接下来我们就要重点分析如何将这些垃圾对象回收掉标记-清除算法标记-清除很容易理解,该算法有两个过程,标记过程和清除过程,标记过程中通过上⽂提到的可达性分析法来标记出所有的⾮垃圾对象,然后再通过清除过程进⾏清理⽐⽅说,我们现在有下⾯的这样的⼀个Java堆,已经通过可达性分析法来标记出所有的垃圾对象(⽤橙⾊表明,蓝⾊的是普通对象):然后我们通过清除阶段进⾏清理,结果是下图:发现什么问题了吗,没错,清理完后的空间是不连续的,也就是说,整个算法最⼤的缺点就是:会出现⼤量的空间碎⽚,当需要分配⼤对象时,会触发FGC,⾮常消耗性能这⾥引出⼀个FGC的概念,为了避免主题跑偏,本⽂中暂时不进⾏深⼊,只需要知道垃圾回收分为YGC(年轻代垃圾回收)和FGC(完全垃圾回收),可以把YGC理解为扫扫地,倒倒垃圾,把FGC理解为给家⾥来个⼤扫除复制算法复制算法将Java堆划分为两块区域,每次只使⽤其中的⼀块区域,当垃圾回收发⽣时,将所有被标记的对象(GC Roots可达,为⾮垃圾对象)复制到另⼀块区域,然后进⾏清理,清理完成后交换两块区域的可⽤性这种⽅式因为每次只需要⼀整块⼀起删除即可,就不⽤⼀个个地删除了,同时还能保证另⼀块区域是连续的,也解决了空间碎⽚的问题整个流程我们再来看⼀遍1.⾸先我们有两块区域S1和S2,标记为灰⾊的区域为当前激活可⽤的区域:2.对Java堆上的对象进⾏标记,其中蓝⾊的为GC Roots可达的对象,其余的均为垃圾对象:3.接下来将所有可⽤的对象复制到另⼀块区域中:4.将原区域中所有内容删除,并将另⼀块区域激活这种⽅法的优缺点也很明显:优点:解决了空间不连续的问题缺点:空间利⽤率低(每次只使⽤⼀半)为了解决这⼀缺点,就引出了下⾯这个算法优化的复制算法⾄于为什么不另起⼀个名字,其实是因为这个算法也叫做复制算法,更确切的说,刚才介绍的只是优化算法的雏形,没有虚拟机会使⽤上⾯的那种复制算法,所以接下来要讲的,就是真正的复制算法这个算法的思路和刚才讲的⼀样,不过这个算法将内存分为3块区域:1块Eden区,和2块Survivor区,其中,Eden区要占到80%这两块Survivor区就可以理解为我们刚才提到的S1和S2两块区域,我们每次只使⽤整个Eden区和其中⼀块Survivor区,整个算法的流程可以简要概括为:1.当发⽣垃圾回收时,将Eden区+Survivor区中仍然存活的对象⼀次性复制到另⼀块Survivor区上2.清理掉Eden区和使⽤的Survivor区中的所有对象3.交换两块Survivor的激活状态光看⽂字描述⽐较抽象,我们来看图像的形式:1.我们有以下这样的⼀块Java堆,其中灰⾊的Survivor区为激活状态2.标记所有的GC Roots可达对象(蓝⾊标记)3.将标记对象全部复制到另⼀块Survivor区域中4.清理掉Eden区和激活的Survivor区中的所有对象,然后交换两块区域的激活状态以上就是整个复制算法的全过程了,有⼈可能会问了,为什么Survivor区这么⼩,就不怕放不下吗?其实平均来说,每次垃圾回收的时候基本都会回收98%左右的对象,也就是说,我们完全可以保证⼤部分情况下剩余的对象都⼩于10%,放在⼀块Survivor区中是没问题的。
JVM系统结构

一、Java平台的结构图二、JVM与JRE、JDK关系?JVM:Java Virtual Machine(Java虚拟机),负责执行符合规范的Class文件JRE:Java Runtime Environment (java运行环境),包含JVM和类库JDK:Java Development Kit(java开发工具包),包含JRE和开发工具包,例如javac、javah相关文章:三、JVM所处的位置:(1)通常工作中所接触的基本是Java库和应用以及Java核心类库,知道如何使用就可以了,但是归根结底代码都是要编译成class文件由Java虚拟机装载执行,所产生的结果或者现象都可以通过Java虚拟机的运行机制来解释。
一些相同的代码会由于虚拟机的实现不同而产生不同结果。
(2)在Java平台的结构中, 可以看出,Java虚拟机(JVM) 处在核心的位置,是程序与底层操作系统和硬件无关的关键。
它的下方是移植接口,移植接口由两部分组成:适配器和Java 操作系统, 其中依赖于平台的部分称为适配器;JVM 通过移植接口在具体的平台和操作系统上实现;在JVM 的上方是Java的基本类库和扩展类库以及它们的API,利用Java API 编写的应用程序(application) 和小程序(Java applet) 可以在任何Java平台上运行而无需考虑底层平台, 就是因为有Java虚拟机(JVM)实现了程序与操作系统的分离,从而实现了Java 的平台无关性。
(3)对JVM规范的的抽象说明是一些概念的集合,它们已经在书《The Java Virtual Machine Specification》(《Java虚拟机规范》)中被详细地描述了;对JVM的具体实现要么是软件,要么是软件和硬件的组合,它已经被许多生产厂商所实现,并存在于多种平台之上;运行Java程序的任务由JVM的运行期实例单个承担。
(4)JVM可以由不同的厂商来实现。
Java工程师学习之路思维导图

Java⼯程师学习之路思维导图前⾯看Hollis的微信公众号更新了Java⼯程师成神之路的⽂档,感觉⾥⾯的内容清晰、齐全,可以⽤来审视⾃⼰,也能够知道⾃⼰在那些⽅⾯可以继续前⾏,想着有时间分享出来。
⼀、基础篇JVMJVM内存结构堆、栈、⽅法区、直接内存、堆和栈区别Ja va内存模型内存可见性、重排序、顺序⼀致性、volatile、锁、final垃圾回收内存分配策略、垃圾收集器(G1)、GC算法、GC参数、对象存活的判定JVM参数及调优Ja va对象模型oop-klass、对象头H o tSpo t即时编译器、编译优化类加载机制classLoader、类加载过程、双亲委派(破坏双亲委派)、模块化(jboss modules、osgi、jigsaw)虚拟机性能监控与故障处理⼯具jps, jstack, jmap、jstat, jconsole, jinfo, jhat, javap, btrace、TProfiler编译与反编译javac 、javap 、jad 、CRFJava基础知识阅读源代码String、Integer、Long、Enum、BigDecimal、ThreadLocal、ClassLoader & URLClassLoader、ArrayList & LinkedList、 HashMap & LinkedHashMap & TreeMap & CouncurrentHashMap、HashSet & LinkedHashSet & TreeSetJa va中各种变量类型熟悉Ja va Str ing的使⽤,熟悉String的各种函数JDK 6和JDK 7中substring的原理及区别、replaceFirst、replaceAll、replace区别、String对“+”的重载、String.valueOf和Integer.toString的区别、字符串的不可变性⾃动拆装箱Integer的缓存机制熟悉Ja va中各种关键字transient、instanceof、volatile、synchronized、final、static、const 原理及⽤法。
Java学习笔记之Java虚拟机JVM

Java虚拟机的生命周期一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序。
程序开始执行时他才运行,程序结束时他就停止。
在同一台机器上运行三个程序,就会有三个运行中的Java虚拟机。
Java虚拟机总是开始于一个main()方法,这个方法必须是公有、返回void、只接受一个字符串数组。
在程序执行时,你必须给Java虚拟机指明这个包含main()方法的类名。
main()方法是程序的起点,只要Java虚拟机中还有普通的线程在执行,Java虚拟机就不会停止。
如果有足够的权限,你可以调用exit()方法终止程序。
JVM物理结构JVM物理结构主要包括两个子系统和两个组件。
两个子系统分别是Classloader(类加载器子系统)和Executionengine(执行引擎)子系统;两个组件分别是Runtimedataarea(运行时数据区域)组件和Nativeinterface(本地接口)组件。
类加载器子系统的作用:根据给定的权限定名类名(如ng.Object)来装载class文件的内容到Runtimedataarea中的methodarea(方法区域)。
Java程序员可以ng.ClassLoader类来写自己的Classloader。
执行引擎子系统的作用:执行classes中的指令。
任何JVMspecification实现(JDK)的核心都是Executionengine,不同的JDK例如Sun的JDK和IBM的JDK好坏主要就取决于他们各自实现的Executionengine 的好坏。
本地接口组件:与nativelibraries交互,是其它编程语言交互的接口。
当调用native方法的时候,就进入了一个全新的并且不再受虚拟机限制的世界,所以也很容易出现JVM无法控制的nativeheap out of Memory。
运行数据域组件:这就是我们常说的JVM的内存了。
它主要分为五个部分——1、Heap(堆):一个Java虚拟实例中只存在一个堆空间2、MethodArea(方法区域):被装载的class的信息存储在Methodarea的内存中。
jvm虚拟机运行原理

jvm虚拟机运行原理
JVM(Java Virtual Machine)是Java语言的运行环境,它是一
个虚拟机,可以在不同的操作系统上运行Java程序。
JVM的
运行原理主要包括以下几个方面:
1. 类加载:JVM通过类加载器加载字节码文件,将字节码文
件转换为可以在JVM上运行的机器码。
类加载过程中包括类
的加载、验证、准备、解析和初始化等阶段。
2. 内存管理:JVM将内存划分为不同的区域,包括方法区、堆、栈、本地方法栈和程序计数器等。
其中堆内存用于存储对象实例,栈内存用于存储方法的局部变量、参数和方法调用栈。
JVM通过垃圾回收器管理堆内存,自动回收不再使用的对象。
3. 字节码解释执行:JVM将字节码文件解释成机器码指令,
并执行这些指令。
JVM中使用解释器和即时编译器两种方式
执行字节码文件。
解释器逐条解释执行字节码指令,而即时编译器会将热点代码(经常被执行的代码)编译成本地机器码,提高执行效率。
4. 异常处理:JVM对Java程序中的异常进行处理。
当程序发
生异常时,JVM会根据异常处理器的设置来决定如何处理异常,包括捕获异常、抛出异常和中断程序等。
5. 多线程支持:JVM支持多线程的并发执行。
JVM会为每个
线程分配一个栈用于存储线程的局部变量和方法调用栈,同时使用线程调度器来管理线程的执行顺序。
总体来说,JVM的运行原理包括类加载、内存管理、字节码解释执行、异常处理和多线程支持等方面,通过这些机制使得Java程序可以跨平台运行。
JVM原理速记复习Java虚拟机总结思维导图面试必备

JVM原理速记复习Java虚拟机总结思维导图⾯试必备良⼼制作,右键另存为保存JVM喜欢可以点个赞哦Java虚拟机⼀、运⾏时数据区域线程私有程序计数器记录正在执⾏的虚拟机字节码指令的地址(如果正在执⾏的是Native⽅法则为空),是唯⼀⼀个没有规定OOM(OutOfMemoryError)的区域。
Java虚拟机栈每个Java⽅法在执⾏的同时会创建⼀个栈桢⽤于存储局部变量表、操作数栈、动态链接、⽅法出⼝等信息。
从⽅法调⽤直到执⾏完成的过程,对应着⼀个栈桢在Java虚拟机栈中⼊栈和出栈的过程。
(局部变量包含基本数据类型、对象引⽤reference和returnAddress类型)本地⽅法栈本地⽅法栈与Java虚拟机栈类似,它们之间的区别只不过是本地⽅法栈为Native⽅法服务。
线程公有Java堆(GC区)(Java Head)⼏乎所有的对象实例都在这⾥分配内存,是垃圾收集器管理的主要区域。
分为新⽣代和⽼年代。
对于新⽣代⼜分为Eden空间、FromSurvivor空间、To Survivor空间。
JDK1.7 ⽅法区(永久代)⽤于存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
对这块区域进⾏垃圾回收的主要⽬的是对常量池的回收和对类的卸载,但是⼀般难以实现。
HotSpot虚拟机把它当做永久代来进⾏垃圾回收。
但很难确定永久代的⼤⼩,因为它受到很多因素的影响,并且每次Full GC之后永久代的⼤⼩都会改变,所以经常抛出OOM异常。
从JDK1.8开始,移除永久代,并把⽅法区移⾄元空间。
运⾏时常量池是⽅法区的⼀部分Class⽂件中的常量池(编译器⽣成的字⾯量和符号引⽤)会在类加载后被放⼊这个区域。
允许动态⽣成,例如String类的intern()JDK1.8 元空间原本存在⽅法区(永久代)的数据,⼀部分移到了Java堆⾥⾯,⼀部分移到了本地内存⾥⾯(即元空间)。
元空间存储类的元信息,静态变量和常量池等放⼊堆中。
Java深入:JVM内存堆布局图解分析

Java深入:JVM内存堆布局图解分析JAVA能够实现跨平台的一个根本原因,是定义了class文件的格式标准,凡是实现该标准的JVM都能够加载并解释该class文件,据此也可以知道,为啥Java语言的执行速度比C/C 语言执行的速度要慢了,当然原因肯定不止这一个,如在JVM中没有数据寄存器,指令集使用的是栈来保存中间数据…等,尽管Java的贡献者们为执行速度的提高想了各种办法,如JIT、动态编译器等,以下是Leetcode中一道题目用不同的语言实现时的执行性能对比图…以下是JVM的一个基本架构图,在这个基本架构图中,栈有两部份,Java线程栈以及本地方法栈,栈的概念与C/C 程序基本上都是一个概念,里面存放的都是栈帧,一个栈帧代表的就是一个函数的调用,在栈帧里面存放了函数的形参,函数的局部变量, 返回地址等,但是与C/C 的一个重要区别是,C/C 里面有传值以及传址的区别,当传的是一个对象时(结构体也可以当成对象,其实就是对象~,只不过里面的方法默认都是public的,不信你可以试试,在结构体中加一个函数,编译器也不会报错,程序依旧运行~~~),会将对象复到到栈中,而Java 中只有基本类型才是传值的,其他类型传的都是引用,什么是引用,学过C/C 的就把引用当作指针理解吧~~~,在这个基本架构图中,可以看出JVM还定义了一个本地方法栈,本地方法栈是为Java调用本地方法【这些本地方法是由其他语言编写的】服务的上面的图中看到的是JVM中栈有两个,但是堆只有一个,每一个线程都有自已的线程栈【线程栈的大小可以通过设置JVM的-xss参数进行配置,32位系统下,JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K】,线程栈里面的数据属于该线程私有,但是所有的线程都共享一个堆空间,堆中存放的是对象数据,什么是对象数据,排除法,排除基本类型以及引用类型以外的数据都将放在堆空间中。
其中方法区和堆是所有线程共享的数据区。
JVM体系结构之一:总体介绍

JVM体系结构之⼀:总体介绍⼀、Java的内存区域划分Java 虚拟机在执⾏Java程序的时候会把它管理的内存区域划为⼏部分,这⼀节我们就来解析⼀下Java的内存区域。
Java的内存区域主要分为五部分:程序计数器(PC)Java 虚拟机栈(JVM Stack)本地⽅法栈(Native Method Stack)Java 堆内存(Java Heap)⽅法区(Method Area)1.1、按照功能1.2、按照内存是否共享类装载器(ClassLoader)(⽤来装载.class⽂件)执⾏引擎(执⾏字节码,或者执⾏本地⽅法)运⾏时数据区(⽅法区、堆、java栈、PC寄存器、本地⽅法栈),如下图:下⾯我们来解析这⼏个区域。
1、程序计数器程序计数器(Program Counter Register)是⼀块较⼩的内存空间,它的作⽤可以看做是当前线程所执⾏的字节码的信号指⽰器。
每⼀条JVM线程都有⾃⼰的PC寄存器在任意时刻,⼀条JVM线程只会执⾏⼀个⽅法的代码。
该⽅法称为该线程的当前⽅法(Current Method)如果该⽅法是java⽅法,那PC寄存器保存JVM正在执⾏的字节码指令的地址,如果该⽅法是native,那PC寄存器的值是undefined。
此内存区域是唯⼀⼀个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
2、Java 虚拟机栈Java虚拟机栈也是线程私有的,每⼀条线程都拥有⾃⼰私有的Java虚拟机栈,它与线程同时创建。
并且⽣命周期与线程相同。
它描述了Java⽅法执⾏的内存模型:每个⽅法在执⾏的同时都会创建⼀个栈帧,⽤于存储局部变量表、操作数栈、动态链接、⽅法出⼝等信息。
每⼀个⽅法从调⽤直⾄完成的过程,都对应⼀个栈帧从⼊栈到出栈的过程。
关于栈帧详细的内容在后边复习虚拟机字节码执⾏引擎的时候再说吧。
Java 虚拟机栈在⽅法调⽤和返回中也扮演了很重要的⾓⾊。
因为除了栈帧的⼊栈和出栈之外,Java虚拟机栈不会再受其它因素的影响,因此栈帧可在系统的堆上分配内存(注意,是系统的Heap⽽不是Java Heap)。
jvm执行引擎的工作过程

jvm执行引擎的工作过程JVM(Java Virtual Machine)是Java语言的核心组成部分,它是一种可以在任何平台上运行Java程序的虚拟机。
JVM中最重要的组成部分是执行引擎,它负责将Java代码转换为机器码并执行。
在本篇文章中,我们将深入探讨JVM执行引擎的工作过程。
JVM执行引擎在运行Java程序时,其主要任务是将Java字节码转换为机器码并执行。
在这个过程中,JVM执行引擎分为两个阶段:解释执行和编译执行。
1. 解释执行解释执行是指JVM在执行Java代码时,直接解释每条指令并进行执行。
在这个过程中,JVM执行引擎需要将Java字节码翻译成机器码,并且需要每次执行都进行翻译。
这个过程虽然效率较低,但它使得Java程序可以在不同的平台上运行。
2. 编译执行编译执行是指JVM在执行Java代码时,先将Java字节码编译成机器码,然后再执行机器码。
在这个过程中,JVM执行引擎将Java字节码编译成本地平台的机器码,这样可以大大提高程序的执行效率。
JVM执行引擎的工作过程可以分为以下几个阶段:1. 类加载阶段在类加载阶段,JVM执行引擎会将Java字节码加载到内存中。
在这个过程中,JVM执行引擎需要完成类的加载、验证、准备、解析和初始化等操作。
这个过程可以确保Java程序能够正确地运行,并且可以防止恶意代码的执行。
2. 解释执行阶段在解释执行阶段,JVM执行引擎会将Java字节码解释成机器码并进行执行。
在这个过程中,JVM执行引擎需要将Java字节码翻译成机器码,并且需要每次执行都进行翻译。
这个过程虽然效率较低,但它使得Java程序可以在不同的平台上运行。
3. 编译执行阶段在编译执行阶段,JVM执行引擎会将Java字节码编译成本地平台的机器码。
在这个过程中,JVM执行引擎会使用即时编译器(JIT)将Java 代码转换成机器码。
这样可以大大提高程序的执行效率。
4. 优化阶段在优化阶段,JVM执行引擎会对程序进行优化。
JVM的基本结构及其各部分详解(一)

JVM的基本结构及其各部分详解(⼀)1 java虚拟机的基本结构如图:1)类加载⼦系统负责从⽂件系统或者⽹络中加载Class信息,加载的类信息存放于⼀块称为⽅法区的内存空间。
除了类的信息外,⽅法区中可能还会存放运⾏时常量池信息,包括字符串字⾯量和数字常量(这部分常量信息是Class⽂件中常量池部分的内存映射)。
2)java堆在虚拟机启动的时候建⽴,它是java程序最主要的内存⼯作区域。
⼏乎所有的java对象实例都存放在java堆中。
堆空间是所有线程共享的,这是⼀块与java应⽤密切相关的内存空间。
3)java的NIO库允许java程序使⽤直接内存。
直接内存是在java堆外的、直接向系统申请的内存空间。
通常访问直接内存的速度会优于java 堆。
因此出于性能的考虑,读写频繁的场合可能会考虑使⽤直接内存。
由于直接内存在java堆外,因此它的⼤⼩不会直接受限于Xmx指定的最⼤堆⼤⼩,但是系统内存是有限的,java堆和直接内存的总和依然受限于操作系统能给出的最⼤内存。
4)垃圾回收系统是java虚拟机的重要组成部分,垃圾回收器可以对⽅法区、java堆和直接内存进⾏回收。
其中,java堆是垃圾收集器的⼯作重点。
和C/C++不同,java中所有的对象空间释放都是隐式的,也就是说,java中没有类似free()或者delete()这样的函数释放指定的内存区域。
对于不再使⽤的垃圾对象,垃圾回收系统会在后台默默⼯作,默默查找、标识并释放垃圾对象,完成包括java堆、⽅法区和直接内存中的全⾃动化管理。
5)每⼀个java虚拟机线程都有⼀个私有的java栈,⼀个线程的java栈在线程创建的时候被创建,java栈中保存着帧信息,java栈中保存着局部变量、⽅法参数,同时和java⽅法的调⽤、返回密切相关。
6)本地⽅法栈和java栈⾮常类似,最⼤的不同在于java栈⽤于⽅法的调⽤,⽽本地⽅法栈则⽤于本地⽅法的调⽤,作为对java虚拟机的重要扩展,java虚拟机允许java直接调⽤本地⽅法(通常使⽤C编写)7)PC(Program Counter)寄存器也是每⼀个线程私有的空间,java虚拟机会为每⼀个java线程创建PC寄存器。