通常情况下,我们可以把 JVM 的内存区域划分为以下几个部分,其中,有的区域是以线程作为单位,而有的区域则是整个 JVM 进程唯一的:
1.程序计数器
在 JVM 规范中,每个线程都有自己的程序计数器,并且任何时间一个线程只有一个方法在执行,也就是所谓的当前方法。程序计数器会存储当前线程正在执行的 java 方法的 JVM 指令的地址;但是,如果正在执行的是本地方法,则未指定值。
2.Java 虚拟机栈
虚拟机栈,早期也被称之为 Java 栈。每个线程在被创建时,都会创建一个虚拟机栈,其内部保存了一个个栈帧,对应着一次次 Java 方法的调用。
在上面的计数器中,我们提到了任何一个时间点,一个线程只能执行一个方法,也就是当前方法,类似的,任何一个时间点,一个线程只会有一个活动栈帧,通常叫当前帧,方法所在的类为当前类。如果说该方法中又调用了其他方法,对应的会创建新的栈帧,这个栈帧成为了新的当前帧,一直到它返回结果或者执行结束为止。
JVM 直接对 Java 栈的操作只有两个,即对栈帧的压栈和出栈。
栈帧中存储着局部变量表,操作数栈,动态链接,方法正常退出或者异常退出的定义等。
3.堆
堆是 Java 内存管理的核心区域,用来放置 Java 实例对象。堆被所有的线程共享,在启动虚拟机时,我们可以通过指定 -Xmx
来指定最大的堆空间等指标。
堆也是垃圾回收器重点照顾的对象,所以堆内空间还会被不同的垃圾回收器进一步细分,其中最有名的就是新生代,老年代的划分。
4.方法区
方法区也是被所有线程共享的一块内存区域,用于存储元数据,例如类的结构信息,以及对应的运行时常量池,字段,方法代码等。
在早期的 JVM 实现中,很多人习惯将方法区称为永久代,但是在 JDK 8 中已经将其删除,同时新增了元数据区。
5.运行时常量池
它是方法区的一部分。如果你有分析过反编译的类文件结构,你能看到版本号,字段,方法,父类,接口等各种信息,还有一项信息就是常量池。Java 的常量池可以存放各种常量信息。
6.本地方法栈
它和虚拟机栈很类似,支持对本地方法的调用,同样也是每个线程创建一个。
下面上一张 JVM 内存区域划分的图:
内存溢出通俗的讲就是内存不够用了,并且 GC 通过垃圾回收也无法提供更多的内存。实际上除了程序计数器,其他区域都有可能发生 OOM, 简单总结如下:
堆内存不足是最常见的 OOM 原因之一,抛出错误信息 java.lang.OutOfMemoryError:Java heap space
,原因也不尽相同,可能是内存泄漏,也有可能是堆的大小设置不合理。
对于虚拟机栈和本地方法栈,导致 OOM 一般为对方法自身不断的递归调用,且没有结束点,导致不断的压栈操作。类似这种情况,JVM 实际会抛出 StackOverFlowError
, 但是如果 JVM 试图去拓展栈空间的时候,就会抛出 OOM.
对于老版的 JDK, 因为永久代大小是有限的,并且 JVM 对老年代的内存回收非常不积极,所以当我们添加新的对象,老年代发生 OOM 的情况也非常常见。
随着元数据区的引入,方法区内存已经不再那么窘迫,所以相应的 OOM 有所改观,出现 OOM,异常信息则变成了:“java.lang.OutOfMemoryError: Metaspace”。
RabbitMQ整合SpringBoot做一些简单的消息发送。虽然只是使用了简单的fanout模式推送的消息,不过其他模式也一样,无非就是匹配路由键的规则。RabbitMQ的定义和规则可以看看这里:https://blog.csdn.net/xianyun1992/article/details/107699839创建SpringBoot项目:1、首先创建一个普通的SpringBoot项目,添加RabbitMQ的maven依赖: <dependency>
你的位置:问答吧-> JSP-> 问题详情Statement.excuteQuery()方法中怎么执行多条MySQL语句???String database = (String)request.getParameter("database");String table = (String)request.get..._executequery多条语句
论文链接:https://link.springer.com/content/pdf/10.1023/A:1007379606734.pdf主要内容单任务学习STL多任务学习MTL图1. 四个输入相同的任务的单任务后向传播、图2展示了一个输入与图1中的四个网络一致的单一网络,但该网络有四个输出,每个输出对应图1中的一个任务。需要注意的是,这些输出可以连接他们共享的一个隐层的所有神经元..._multitask learning代码
在windows 和 linux下引入hash_set、hash_map头文件推荐使用方法:在源代码的前面写入一下代码:// just for "#include " in linux#if __GNUC__>2#include #include us_google dense_hash_map linux下使用
写在vue之前1.代码规范2.邮件抄送3.OOCSS就是把每一种样式抽离出来, 样式复用, 比如bootstarp的buttom4.BEM 命名规范块block, 元素element, 修饰符modifierhttps://www.w3cplus.com/css/bem-definitions.htmlhttps://en.bem.info/methodology/..._pitayadog
解决办法:1.检查本地计算机时间是否正确,如果时间超出使用时间范围会报此错误,更正即可2.如果是用的是高版本,可以改成低版本,我的是57,改为56即可3.或者在控制台net start MySQL时,出现MySQL服务无法启动,服务没有报告任何错误。 A:进入bin目录,执行一下初始化 mysqld --initialize,再次net start MySQL就解决了。(本...
Given a set ofdistinctintegers,nums, return all possible subsets (the power set).Note:The solution set must not contain duplicate subsets.Example:Input: nums = [1,2,3]Output:[ [3], [1...
一.单一职责原则 单一职责原则是最简单的面向对象设计原则,它用于控制类的粒度大小。单一职责原则定义如下:单一职责原则(Single Responsibility Principle, SRP):一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。 单一职责原则告诉我们:一个类不能太“累”!在软件系统中,一个类(大到模块,小到方法..._接口会越来越多 要用什么设计模式
【上线前流程】将测试环境修改成正式环境修改版本号,而且build version比version多一位,如version设置为1.0.1,那么build就设置成1.0.1.x;这么做的理由是,当你这次提交审核一旦没有通过,提交的应用包(忘了正式名字了)没法撤销,再次上传的时候他会提示你该版本已经上传了,无法上传之类的;当然build version也可以用别的形式命名,比如1024什么的(滑稽)_对于ios开发完整流程
基本数据类型参数传递: 主函数进栈,定义x变量并赋值;调用show方法,show方法进栈,定义变量x;将参数x赋值给show方法中的x,此时show方法中的x为3;将show方法中的x赋值为4;默认有一个return语句,结束函数,show方法出栈(弹栈);执行main函数里的输出语句,输出的值为3。
出发点2018年年初开始了处女作的编写,并在当年10月上线《从零开始学Python数据分析与挖掘》。在编写处女作的同时也在想另一件事,即一名合格的数据分析师需要掌握哪些硬技能,才能在实操环节中做到游刃有余?相信很多即将踏出校门或转行的朋友都非常关心这个问题,包括已经从事数据分析师的朋友。抱着这个疑问,我首先扪心自问,回顾过往的工作经历。再去寻求其他高级数据分析师或资深数据分析师的观点,几..._pandas一年一条折线图
如何判断java对象已经被回收?看完秒懂_java如何判断对象被回收