Java虚拟机系列之Java内存结构简介
本文我们将讲解Java虚拟机中各个区域以及各个区域的作用。
一.程序计数器
什么是程序计数器,有什么作用?
程序技术器是一块比较小的内存区域,主要当做是线程中所执行的字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选取下一个执行的字节码命令,分支、循环、跳转等基础功能都是依赖这个程序计数器来完成。
有什么特点?
Java虚拟机中的多线程是通过线程轮流切换分配处理器执行时间的方式来实现的,所以为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,所以是线程私有的。
注意:
如果线程执行的是Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Native方法,这个计数器的值为空,此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemory的情况的区域
二.Java虚拟机栈
Java虚拟机栈是干嘛的?
Java虚拟机栈描述的是Java内存模型,每个方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法返回地址等信息。每一个方法从调用到执行结束对应着一个栈帧在虚拟机栈中入栈出栈的过程。
有什么特点?
Java虚拟机栈是线程私有的,而且生命周期和线程相同。
注意:
如果线程请求的栈的深度大于虚拟机所允许的深度,将抛出StackOverFlowError异常;如果虚拟机栈可以动态扩展,如果扩展时无法申请到足够多的内存,就会抛出OutOfMemoryError异常。
三.本地方法栈
与虚拟机栈发挥的功能类似,区别不过是虚拟机栈为虚拟机执行Java方法,本地方法栈为虚拟机用到的Native方法服务。本地方法栈也会抛出StackOverFlowError和OutOfMemoryError异常。
四.Java堆
什么是Java堆,有什么作用?
Java堆是Java虚拟机中所管理内存中最大的,是所有线程共享的一块内存区域,在虚拟机启动的时候创建,目的是存放对象实例。
有什么特点?
几乎所有的对象实例都在这里分配内存,因此这也是垃圾收集器管理最主要的区域,而且Java堆可以处于物理不连续的内存空间,只要逻辑连续即可
1、Java堆中还细分新生代和老年代,然后新生代中又分为Eden区域、From Survivor空间、To Survivor空间等。
2、这里的Java堆的垃圾回收算法是使用了分代收集算法,即新生代中使用“复制”算法,而老年代中使用“标记-清理”算法或“标记-整理”算法。
注意:
当前主流虚拟机都是可扩展来实现的(通过-Xms和-Xmx来控制),如果堆中没有内存完成实例,并且堆也无法再扩展时,会抛出OutOfMemoryError异常。
五.方法区
方法区的作用是什么?
方法区是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即使编译器编译后的代码等数据。
为啥说方法区不等价于永久区?
方法区不等价于永久代,只是HotSpot虚拟机的设计团队选择把GC分代收集扩展至方法区,是为了HotSpot垃圾收集器可以像管理Java堆一样管理这部分内存,能够省去专门为方法区编写内存管理代码的工作,但是这样也会更容易造成内存溢出的问题(永久代可以用-XX:MaxPermSize设置上限),所以在JDK1.7的HotSpot已经把永久代的字符串常量池移出,移到了Java Heap区,可在 《深入解析String#intern》 了解
运行时常量池有什么作用?
运行时常量池也是方法区的一部分,用于存放编译期生成的各种字面量和符号引用,这部分将在类加载后进入方法区的运行时存放。
运行时常量池的特点?
- Java虚拟机对Class文件每一部分的格式都有严格规定,每一个字节用于存储哪种数据都必须符合规范上的要求才会被虚拟机认可、装载和执行,然而对于运行时常量池却没做任何要求
- 运行时常量具有动态性,可以在运行期间将新的常量放入池中,比如String的intern()方法
六.直接内存
直接内存是Java虚拟机的内存吗?
直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范定义的内存区域,是使用本机的内存,又名堆外内存。
怎么在Java中使用堆外内存?
在JDK1.4中的NIO类,引入了基于通道(Channel)与缓冲区(Buffer)的I/O方式,可以使用Native函数库来直接分配堆外内存,然后在Java堆中使用DirectByteBuffer对象来作为这块内存的引用进行操作。
注意:
虽然堆外内存不受Java堆大小的管理,但是受本机总内存以及处理器寻址空间的限制。在服务器管理员配置虚拟机参数的时候,可以通过-Xmx等来配置Java虚拟机最大内存,但经常忽略直接内存,导致各个内存区域总和大于物理内存限制,导致OutOfMemoryError异常。
如果本文有什么疑问或者是错误,欢迎指出留言,互相学习
如果对自己未来有想法,想提升自己,你现在在JAVA这条路上挣扎,也想在IT行业拿高薪,可以参加我们免费的公开课试听学习 干货满满的,选择最适合自己的课程学习,技术大牛亲授,课程内容有:Java工程化、高性能及分布式、高性能、深入浅出。高架构。性能调优、Spring,MyBatis,Netty源码分析和大数据等多个知识点。如果你想拿高薪的,想学习的,想就业前景好的,想跟别人竞争能取得优势的,想进阿里面试但担心面试不过的,你都可以来。
群号:468947140
进群修改群备注:开发年限-地区-经验
点击链接加入群聊【Java-BATJ企业级资深架构】:https://jq.qq.com/?_wv=1027&k=52j2FVO

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
jvm分析工具和查看命令
jinfo 可以输出并修改运行时的java 进程的opts。 jps 与unix上的ps类似,用来显示本地的java进程,可以查看本地运行着几个java程序,并显示他们的进程号。 jstat 一个极强的监视VM内存工具。可以用来监视VM内存内的各种堆和非堆的大小及其内存使用量。 jmap 打印出某个java进程(使用pid)内存内的所有'对象'的情况(如:产生那些对象,及其数量)。 jconsole 一个java GUI监视工具,可以以图表化的形式显示各种数据。并可通过远程连接监视远程的服务器VM。 详细:在使用这些工具前,先用JPS命令获取当前的每个JVM进程号,然后选择要查看的JVM。 jstat工具特别强大,有众多的可选项,详细查看堆内各个部分的使用量,以及加载类的数量。使用时,需加上查看进程的进程id,和所选参数。以下详细介绍各个参数的意义。 jstat -class pid:显示加载class的数量,及所占空间等信息。 jstat -compiler pid:显示VM实时编译的数量等信息。 jstat -gc pid:可以显示gc的信息,查看gc的次数,及时间。其中最后五项,...
-
下一篇
手把手 | 用Python语言模型和LSTM做一个Drake饶舌歌词生成器
未来AI的主要应用是在建立能够学习数据然后生成原创内容的网络。这个想法已经充分应用于在自然语言处理(NLP)领域,这也是AI社区能够搭建出所谓语言模型的原因:语言模型的前提是学习句子在文章段落中的组成结构,从而生成新的内容。 在这篇文章中,我想尝试生成与很受欢迎的加拿大说唱歌手Drake(a.k.a. #6god)风格类似的说唱歌词,这肯定是件很有趣的事儿。 另外,我还想分享一下常规的机器学习项目渠道,因为我发现很多同学想做一些小项目,但不知道该从何处入手。 获取数据 首先,我们开始搜集Drake的曲库,为了节省时间我直接写了个爬虫,从网页metrolyrics.com抓取歌词。 import urllib.request as urllib2 from bs4 import BeautifulSoup import pandas a
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS6,CentOS7官方镜像安装Oracle11G
- Dcoker安装(在线仓库),最新的服务器搭配容器使用
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2全家桶,快速入门学习开发网站教程