JVM学习——内存空间(学习过程)
JVM——内存空间
关于内存的内容,内存的划分。JVM1.7 -> 1.8的变化比较大
JVM指令执行的时候,是基于栈的操作。每一个方法执行的时候,都会有一个属于自己的栈帧的数据结构。栈的深度,在编译为Class文件的时候,就已经能够确定好了。还能够看到栈的最大深度。
要涉及的知识点(学习路线):
JVM包含的内存空间布局
- 虚拟机栈:Stack Frame 栈帧。引用本身是一个变量,在虚拟机栈中存储。
- 程式计数器(Program Counter)。
- 本地方法栈:native,主要用于执行本地方法。
- 堆(heap):最大的空间-共享区域。存放一个个的对象实例。与堆相关的一个重要概念是垃圾收集器。现在几乎所有的垃圾收集器都是采用分代收集算法。所以堆空间也基于这一点进行了相应的划分:新生代与老年代。Eden空间,From Survivor空间与To Survivor空间。
- 方法区(method Area):存储元信息。永久代(Permanent Generation)从JDK1.8开始,已经彻底废弃了永久代。使用元空间(meta space)来替代。
- 运行时的常量池:方法区的一部分。
- 直接内存:Direct Memory。不是JVM管理的,是由计算机或者硬件来操作的。JVM只是能够申请一片内存区使用。与Java NIO密切相关。JVM通过堆上的DirectByteBuffer来操作直接内存。
Java对象内存分配原理与布局
一个对象由两部分组成:数据,元数据。(不在同一个地方)。元数据是存在堆的方法区的。
对象的两种实现方式
- 指针指向 两个都是指针的
- 指针指向 一个指针的
堆的压缩:涉及到对象的移动。如果对象发生移动,地址就会变了。如果采用上面第一次,就会经常发生变化。如果用第二种,第二种就算位置变,也只是引用的位置变。所以Oracle的HotSpot采用的是第二种实现方式。
- 程序计数器和栈 都是线程私有的。
- 如果是8个基本类型的值,是直接放在栈里面的。
- 引用是放在栈里面的。生成的对象是方法
- 本地方法栈:主要是跟native方法有关的。 和虚拟机栈没什么本质区别。
- 堆是主要的内存空间。堆内存的空间是共享的。
- 老年代和新年待。老年代的回收频率比新生代频率低的很多。
- java的堆空间,在物理空间上,既可以是连续的。也可以是不连续的
- 方法区:不是存放方法的区域。主要存放的是元信息。元信息和永久代不是一个概念。永久代永远不会被回收掉。元信息也是一般情况下,不会被收集的。这也是容易混淆的原因。但是比如Class的元信息。在Class被卸载的时候,元信息也是会被回收的。
关于Java对象创建的过程:
new 关键字创建对象的三个步骤:
- 在堆内存中创建出对象实例
- 为对象的成员变量赋初始值
- 将对象的引用返回
- 指针碰撞(前提是堆中的空间通过一个指针进行分割,一侧是已经被占用的空间,另一侧是未被占用的空间)
- 空闲列表(前提是堆内存空间中已被使用与未被使用的空间是交织在一起的,这时,虚拟机就需要通过一个列表来记录哪些空间是可使用的,哪些空间是已经被使用的,接下来找出可以容纳下新创建对象的且未被使用的空间,在此空间存放该对象。同时还要修改列表上的记录)
- 对象在内存中的布局
- 对象头
- 实例数据(即我们在一个类中所声明的各项信息)
- 对其填充(可选)
- 引用访问对象的方式:
- 使用句柄的方式。
- 使用直接指针的方式。
堆内存溢出异常
运行此程序,内存溢出:(此时电脑会起飞)
package com.dawa.jvm.memory;
import java.util.ArrayList;
import java.util.List;
public class MyTest {
public static void main(String[] args) {
List<MyTest> list = new ArrayList<>();
for (; ; ) {
list.add(new MyTest());
}
}
}
使用虚拟机参数设定整个JVM对空间的大小,并且溢出的时候,打印到硬盘上(转储)。
参数:-Xms5m
-Xmx5m
-XX:+HeapDumpOnOutOfMemoryError
溢出异常
使用jvisualVM工具:(我本地Mac打不开,可能跟安装的版本有关) 还有个 Jconsole
Last login: Tue Feb 18 17:25:06 on ttys000
➜ ~ jvisualvm
Unable to locate an executable at "/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/bin/jvisualvm" (-1)
➜ ~
当我们内存溢出的时候,我们可以很好的借助这种工具来判断是哪个类运行的多,哪个类浪费了空间。
接下来,我们加一行 System.gc()
再次运行的时候:内存不会溢出
内存没满
并且垃圾回收活动很频繁
堆空间大小:一直保持在2m左右
还有一个工具:Jconsole(如下图)
虚拟机栈溢出异常
虚拟机栈溢出案例
使用递归,并且设置虚拟机栈的大小:
设置虚拟机栈大小的虚拟机参数:-Xss100k
栈大小最少需要160K。
设置为160k
所以:运行之后就直接栈溢出。Stack Overflow
点击右上角的Dump。抓取一些线程的信息
看看就行了。
这些工具就在这里,一些人不知道,所以没用过。如果有需要,就拿去用。
JConsole 工具的使用
还提供了 检测死锁的功能。
如何用代码写出死锁,检测死锁和分析工具的深度解析
死锁:产生的条件:两个线程,互相持有相应的锁,对象去访问
package com.dawa.jvm.memory;
public class MyTest3 {
public static void main(String[] args) {
new Thread(A::method,"Thread-A").start();
new Thread(B::method,"Thread-A").start();
}
}
//方法的锁,是所在类的锁.
class A{
public static synchronized void method(){
System.out.println("method from A");
try {
Thread.sleep(5000);
B.method();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class B{
public static synchronized void method(){
System.out.println("method from B");
A.method();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
JVisualVM软件更好使,进来之后,直接提示线程死锁。(Dump一下)
准备锁定的和已经锁定的。AB线程相互相反
over,合理利用工具。
方法区产生内存溢出异常
采用手段
显示设定元空间的大小。让它不会自动扩展
因为存放的都是数据的元信息。采取特殊手段进行(运行期动态生成类 如CGlib)
方法区产生内存溢出异常.
在运行期间不断的生成新的对象,元数据会不断的放入元空间.
元空间默认占用内存21兆.如过不修改配置,会自动扩容(扩容到物理内存大小)
创建一个程序,不断的创建子类。元信息会不断的放入元空间当中。
虚拟机参数设置:

编写程序:
查看结果: Metaspace(1.7版本之前,是老年代。所以看网上文字的时候,注意时效性和带着批判的眼光去学习)
使用Jconsole 连接此线程
如果勾选,详细输出,那么控制台也会打印很多东西:
通过CGlib 在运行过程中生成的类:
使用JVisualVM来查看 元空间的变化呈现上升趋势
当到达200M的上线的时候,程序退出
那么,元空间到底是什么?
https://www.infoq.cn/article/Java-PERMGEN-Removed/
通过这篇文章,对其理解。可以理清JDK8中去除永久代的重要事实。
JMap 和Jstat和JCMD的使用
JDK提供的一些命令行工具。
jmap
➜ ~ jmap
Usage:
jmap [option] <pid>
(to connect to running process)
jmap [option] <executable <core>
(to connect to a core file)
jmap [option] [server_id@]<remote server IP or hostname>
(to connect to remote debug server)
where <option> is one of:
<none> to print same info as Solaris pmap
-heap to print java heap summary
-histo[:live] to print histogram of java object heap; if the "live"
suboption is specified, only count live objects
-clstats to print class loader statistics
-finalizerinfo to print information on objects awaiting finalization
-dump:<dump-options> to dump java heap in hprof binary format
dump-options:
live dump only live objects; if not specified,
all objects in the heap are dumped.
format=b binary format
file=<file> dump heap to <file>
Example: jmap -dump:live,format=b,file=heap.bin <pid>
-F force. Use with -dump:<dump-options> <pid> or -histo
to force a heap dump or histogram when <pid> does not
respond. The "live" suboption is not supported
in this mode.
-h | -help to print this help message
-J<flag> to pass <flag> directly to the runtime system
➜ ~
列出所有的进程,找到端口号
ps -ef | grep java
➜ ~ ps -ef | grep java
501 4619 1183 0 7:44下午 ?? 0:36.29 /Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/bin/java -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -Xmx512m -Dfile.encoding=UTF-8 -Duser.country=CN -Duser.language=zh -Duser.variant -cp /Users/shangyifeng/.gradle/wrapper/dists/gradle-5.2.1-all/bviwmvmbexq6idcscbicws5me/gradle-5.2.1/lib/gradle-launcher-5.2.1.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 5.2.1
501 5368 4053 0 8:41下午 ttys000 0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn java
➜ ~
直接通过Jmap获取当前线程的类加载器
jmap -heap 端口号:4619
下一个工具:
jstat
➜ ~ jstat
invalid argument count
Usage: jstat -help|-options
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
Definitions:
<option> An option reported by the -options option
<vmid> Virtual Machine Identifier. A vmid takes the following form:
<lvmid>[@<hostname>[:<port>]]
Where <lvmid> is the local vm identifier for the target
Java virtual machine, typically a process id; <hostname> is
the name of the host running the target Java virtual machine;
and <port> is the port number for the rmiregistry on the
target host. See the jvmstat documentation for a more complete
description of the Virtual Machine Identifier.
<lines> Number of samples between header lines.
<interval> Sampling interval. The following forms are allowed:
<n>["ms"|"s"]
Where <n> is an integer and the suffix specifies the units as
milliseconds("ms") or seconds("s"). The default units are "ms".
<count> Number of samples to take before terminating.
-J<flag> Pass <flag> directly to the runtime system.
➜ ~
MC:Current Metaspace:当前元空间的大小
MU:Metaspace Utillization :已经被使用的元空间大小
查看当前系统的进程(通用的操作系统的命令)
ps -ef | grep java
JSP命令:查看当前操作系统中的所有进程
➜ ~ jps
5584 Jps
4619 GradleDaemon
1183
JCMD指令
➜ ~ jcmd
5602 sun.tools.jcmd.JCmd
4619 org.gradle.launcher.daemon.bootstrap.GradleDaemon 5.2.1
1183
➜ ~
从JDK1.7开始引入。
➜ ~ jcmd -help
Usage: jcmd <pid | main class> <command ...|PerfCounter.print|-f file>
or: jcmd -l
or: jcmd -h
command must be a valid jcmd command for the selected jvm.
Use the command "help" to see which commands are available.
If the pid is 0, commands will be sent to all Java processes.
The main class argument will be used to match (either partially
or fully) the class used to start Java.
If no options are given, lists Java processes (same as -p).
PerfCounter.print display the counters exposed by this process
-f read and execute commands from the file
-l list JVM processes on the local machine
-h this help
➜ ~
JCMD(常用命令)详解
查看JVM运行参数
jcmd pid VM.flags
列出当前进程,我们能对此进程的操作
jcmd pid help
查看当前某个进程的具体命令的具体参数。
jcmd pid JFR.dump
列出JVM xing能相关的一些参数
jcmd pid PerfCounter.print
查看JVM的启动时长
jcmd pid VM.uptime
查看系统中类的统计信息
jcmd pid GC.class_historgram
查看当前线程的堆栈信息
Thred.print
导出hprof文件,导出的文件可以通过JvisualVM查看。dump
jcmd pid GC.heap_dump [filepath]
查看VM的信息。
jcmd pid VM.system_properties
查看目标JVM进程的版本信息。
jcmd pid VM.version
查看JVM启动的时候携带的参数。
jcm pid VM.command_line
综上,通过JUI能看到的东西,在命令行都是能够出来的。但是有些时候是不能用UI工具的。JDK在官方发布的时候,不只是源码,还携带了很多便携性的工具。
jstack 专门用来查看或者导出Java应用中线程的堆栈信息。
jstack pid
➜ ~ jstack
Usage:
jstack [-l] <pid>
(to connect to running process)
jstack -F [-m] [-l] <pid>
(to connect to a hung process)
jstack [-m] [-l] <executable> <core>
(to connect to a core file)
jstack [-m] [-l] [server_id@]<remote server IP or hostname>
(to connect to a remote debug server)
Options:
-F to force a thread dump. Use when jstack <pid> does not respond (process is hung)
-m to print both java and native frames (mixed mode)
-l long listing. Prints additional information about locks
-h or -help to print this help message
➜ ~
Jmc 和 Jhat 工具的使用
另外两个可视化工具,比JvisualVM显示的内容更多,并且在运行的时候也能够使用。
jmc : Java mission Contrl (我的OpenJDK 打不开)

相当于把所有的jcmd继承在这个 诊断命令这里了
飞行记录器: jfr : java fly recoard. (下图是截取的一段飞行记录器)
热点方法,加载,异常。编译,调用树。等都能查看的非常非常详细。
不管一个人对JVM多了解,一般都是借助UI工具来进行调优的。
借助 此工具,再看一下源空间的数据
Jhat 工具 对堆存储文件的分析工具
jhat filepath
➜ ~ jhat -help
Usage: jhat [-stack <bool>] [-refs <bool>] [-port <port>] [-baseline <file>] [-debug <int>] [-version] [-h|-help] <file>
-J<flag> Pass <flag> directly to the runtime system. For
example, -J-mx512m to use a maximum heap size of 512MB
-stack false: Turn off tracking object allocation call stack.
-refs false: Turn off tracking of references to objects
-port <port>: Set the port for the HTTP server. Defaults to 7000
-exclude <file>: Specify a file that lists data members that should
be excluded from the reachableFrom query.
-baseline <file>: Specify a baseline object dump. Objects in
both heap dumps with the same ID and same class will
be marked as not being "new".
-debug <int>: Set debug level.
0: No debug output
1: Debug hprof file parsing
2: Debug hprof file parsing, no server
-version Report version number
-h|-help Print this help and exit
<file> The file to read
For a dump file that contains multiple heap dumps,
you may specify which dump in the file
by appending "#<number>" to the file name, i.e. "foo.hprof#3".
All boolean options default to "true"
➜ ~
执行命令,启动一个服务器能够浏览器直接访问。
提供了OQL查询,以一种SQL查询的方式,查询相关的数据。相关语法结构等到用的时候现用现学就行了。

这个功能在JvisualVM里面也有所体现。
JVM学习——内存空间(学习过程)的更多相关文章
- jvm的内存空间分区
在方法(代码块)中定义一个变量时,java就在栈中为这个变量分配JVM内存空间,当超过变量的作用域后,java会自动释放掉为该变量所分配的JVM内存空间:而在堆中分配的JVM内存由java虚拟机的自动 ...
- JVM的内存空间
一.JVM运行起来,就会给内存划分空间,这块空间成为运行时数据区.运行时数据区主要划分为以下几部分内容: 1.栈 每一个线程运行起来的都会对应一个栈(线程栈),栈中的数据是该线程独有的,不会产生资源共 ...
- JVM学习--内存分配策略(持续更新)
一.前言 最近学习<深入java虚拟机>,目前看到内存分配策略这块.本文将进行一些实践. 二.内存分配策略 1.大对象直接进入老年代 书中提到了: 下面进行测试,代码如下: public ...
- 调整JVM占用内存空间方法
JVM默认占用空间为64M 调整方法如下图 在虚拟机参数中调整为80M 调试可以用 Byte[] arr=new Byte[1024*1024*64];
- JVM学习(1)——通过实例总结Java虚拟机的运行机制
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: JVM的历史 JVM的运行流程简介 JVM的组成(基于 Java 7) JVM调优参数:-Xmx和-Xms ...
- JVM学习001通过实例总结Java虚拟机的运行机制
JVM学习(1)——通过实例总结Java虚拟机的运行机制-转载http://www.cnblogs.com/kubixuesheng/p/5199200.html 文章转载自:http://www.c ...
- JVM学习--(一)基本原理
前言 JVM一直是java知识里面进阶阶段的重要部分,如果希望在java领域研究的更深入,则JVM则是如论如何也避开不了的话题,本系列试图通过简洁易读的方式,讲解JVM必要的知识点. 运行流程 我们都 ...
- 图解JVM在内存中申请对象及垃圾回收流程
http://longdick.iteye.com/blog/468368 先看一下JVM的内存模型: 从大的方面来讲,JVM的内存模型分为两大块: 永久区内存( Permanent space )和 ...
- JVM学习(1)——通过实例总结Java虚拟机的运行机制(转)
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: JVM的历史 JVM的运行流程简介 JVM的组成(基于 Java 7) JVM调优参数:-Xmx和-Xms ...
随机推荐
- 万级K8s集群背后 etcd 稳定性及性能优化实践
1背景与挑战随着腾讯自研上云及公有云用户的迅速增长,一方面,腾讯云容器服务TKE服务数量和核数大幅增长, 另一方面我们提供的容器服务类型(TKE托管及独立集群.EKS弹性集群.edge边缘计算集群.m ...
- Kubernetes 中的 Pod 安全策略
来源:伪架构师作者:崔秀龙很多人分不清 SecurityContext 和 PodSecurityPolicy 这两个关键字的差别,其实很简单:•SecurityContext 是 Pod 中的一个字 ...
- 服务监控 | 彻底搞懂Dropwizard Metrics一篇就够了
Metrics是一个提供服务性能检测工具的Java类库,它提供了功能强大的性能指标工具库用于度量生产环境中的各关键组件性能. 度量类型 Metrics提供了以下几种基本的度量类型: Gauge:用于提 ...
- Springboot集成邮箱服务发送邮件
一.前言 Spring Email 抽象的核心是 MailSender 接口,MailSender 的实现能够把 Email 发送给邮件服务器,由邮件服务器实现邮件发送的功能. Spring 自带了一 ...
- JVM调优2-远程监控
监控远程JVM VisualJVM不仅是可以监控本地jvm进程,还可以监控远程的jvm进程,需要借助于JMX技术实现. 什么是JMX JMX(Java Management Extensions,即J ...
- 申请Namecheap的.me 顶级域名以及申请ssl认证--github教育礼包之namecheap
关于教育礼包的取得见另一篇随笔,在那里笔者申请了digital ocean的vps(虚拟专用主机),跟阿里云差不多,不过个人感觉比阿里云便宜好用一点. 有了自己的主机ip,就想到申请域名,方便好记,也 ...
- JUC之阻塞队列(BlockingQueue)基础
阻塞队列 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列.这两个附加的操作支持阻塞的插入和移除方法. 阻塞队列常用于生产者和消费者的场景: 当队列为空的,从队列中获取元素的操作将会 ...
- js整体
1.引入 <script type="text/javascript"> 2.输出 使用 window.alert() 写入警告框 使用 document.write ...
- NextCloud + python API
NextCloud库地址:https://github.com/matejak/nextcloud-API 安装库依赖: 安装库: 建议在虚拟环境下使用 使用示例: # -*- coding: utf ...
- TypeScript入门文档
typescript入门文档链接d地址:https://ts.xcatliu.com/basics/type-of-function.html 博主个人站点:www.devloper.top