深度理解JVM
1. 环境搭建
安装jdk
2. 内存溢出场景模拟
public class Test01 { public static void main(String[] args) { //测试内存溢出 List<Demo> list = new ArrayList<Demo>(); while(true) { list.add(new Demo()); } //不停的创建对象会一直消耗堆内存知道内存消耗完(其实不会真的将8G的内存都消耗完) //当达到一个上线时就会报出这个错误了,这时就会报出一个内存溢出 //OutOfMemoryError } }
class Demo{
}
可以在你的项目下找到这个快照的错误文件
但是我们是看不懂的所以需要到http://www.eclipse.org/mat/downloads.php去下载一个eclipse的MemoryAnalyzer分析工具
如果你直接下载会非常慢所以选择一个其他的镜像这样下载就会快点
下载解压后打开
点击file->Open Heap Dump 选中产生的那个文件
然后生成一个
选中这个图标可以查看我们的堆内存运行情况 加载堆内存的信息
这个就代表很可能在main里面出现问题了 占得百分比高达95.6%
Shallow Heap 对象本分所占用的内存大小不包含它的引用对象
Retained Heap 代表当前对象的大小包括当前可直接或者间接引用对象的大小的总和。
点开那个占用堆内存最多线程
继续点开会发现 他创建了很多个这样的对象造成的堆内存溢出
Jvm 的可视化监控工具 这个工具在哪呢在我们安装的jdk中
因为我们的jdk已经配置在我们的path路径下因此在任何路径下都可以访问的到所以在
命令行中可以输入这个值 会将这个可视化界面弹出来
我们可以看到这个图像化界面只有18k那么真正的代码放在了lib目录下的一个jar包里面
这个jps这个命令会列出来所有的java进程,我们看到有JConsole 这个进程 但是为什么没有jps这个进程呢是因为
这个命令执行完之后就结束了。
当我们点进去就能对这个进程进行监控
我们大概就能看到这样的窗口了
java 发展史
1996 . 1 jdk1.0 包含了jvm
- 1996.9 首届 java one 大会
- 1997.2 jdk 1.1 此时提出了内部类,反射,jar的文件格式 jdbc JavaBeans,等也都得到了相应的发展。
- 1998 Jdk1.2 有了3个方向 J2EE(企业级) J2ME(移动开发) J2SE(桌面)
2000 .5 jdk 1.3
2002 .2 jdk 1.4 struts,lHibernate spring1.x
正则表达式
NIO
日志
Xml 解析器
7.2004 . 9 jdk 1.5 自动装箱 泛型 注解 枚举 变长参数 增强for循环
8.2006 jdk 1.6 JavaEE JavaSE JavaME jdk6
提供脚本语言支持
提供了编译api 以及http 服务器api
9. 2009 jdk1.7 Lambda Sun公司 以74亿被收购
Java 之父
詹姆斯 高林斯
Java技术体系
Java程序设计语言
各硬件平台上的java虚拟机
Class文件格式
Java API
第三方的java 类库
Jvm 虚拟机的发展 VM(Memeory Management)
Sun Classic VM 世界上第一款商用的JVM 已经被淘汰了(只能使用纯解释器方式来执行java 代码如果要使用编译器就需要进行外挂,如果外挂了编译器那么这个编译器就会完全接管虚拟机 的执行系统,解释器便不再工作了。) |
Exact VM(准确式 内存管理) 解释器和编译器混合工作以及两级即时编译器 只在Solaris平台发布 英雄气短 性能比Sun Classic VM 高。 |
Hotspot VM (内置了编译器) 以方法为单位进行编译。。。。 |
KVM (kilobyte) 简单,轻量,高度可移植 在手机平台运行 |
JRockit BEA 公司被Oracle 收购了(JRockit Mission Controller):用来诊断泄露并指出根本原因,该工作的开销非常小,因此可以使用他来寻找生产环境中的系统的内存泄漏。它包括三个独立的应用程序,内存泄漏检测器,JVM运行时分析器 和管理控制台。 世界上做快的java 虚拟机 专注服务器端应用 优势: 垃圾收集器MissionControl服务套件 |
J9 IBM IBM Technology for java virtual Machine IT4j |
Azul VM 高性能的java虚拟机 |
Liquid VM |
Dalvik VM 安卓系统所使用的 没有遵循JVM的规范使用的寄存器架构 不是使用JVM的栈架构 使用java 语言进行的开发。谷歌的,效率也比较高。 |
Microsoft JVM |
- Class Loader 类加载器
- Execution Engine 执行引擎 负责解析命令,提交操作系统执行
- Native Interface 本地接口
- Runtime data area 运行数据区
本地方法接口中存放的是 java native interface (JNI) native方法是一种使用java声明c实现的代码
当java 代码执行到含有native的方法时就不在执行而是 调用操作系统的本地方法库交给操作系统和CPU
本地库接口java可以直接调c 我们可以使用double zookle 这些服务型框架避免了底层语言的沟通,
JVM是运行在操作系统之上的,它与硬件没有直接的交互
所谓的JVM调优就是调的是运行时数据区
- Class Loader 类加载器
负责加载class文件,class文件在文件开头有特定的文件标示,并且ClassLoader只负责class文件的加载,
至于它是否可以运行,则由Execution Engine决定
2. Execution Engine 执行引擎负责解释命令,提交操作系统执行。
3. Native Interface 本地接口
Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。
本地接口的作用是融合不同的编程语言为Java所用,它的初衷是融合 C/C++程序,Java诞生的时候是C/C++横行的时候,要想立足,必须有调用C/C++程序,于是就在内存中专门开辟了一块区域处理标记为Native的代码,它的具体做法是Native Method Stack中登记Native方法,在Execution Engine 执行时加载Native libraries。(例如:必须在迅雷下载视屏一样需要先装了迅雷才能让你下视屏)
目前该方法使用的越来越少了,除非是与硬件有关的应用,比如通过Java程序驱动打印机或者Java系统管理生产设备,在企业级应用中已经比较少见。因为现在的异构领域间的通信很发达,比如可以使用Socket通信,也可以使用WebService等等,不多做介绍。
4. Runtime data area 运行数据区
(1)方法区(Method Area)
1: 方法区是线程共享的,通常用来保存装载的类的元结构信息。
比如:运行时常量池+静态变量+常量+字段+方法字节码+在类/实例/接口初始化用到的特殊方法等。
或者:静态变量+常量+类信息+运行时常量池存在于方法区中+实例变量存在堆内存中
简单说,所有定义的方法的信息都保存在该区域。
JVM的优化99%就是优化堆,1%是优化方法区。整个JVM只有这个区域可以优化。
2:通常和永久区关联在一起(Java7之前),但具体的跟JVM的实现和版本有关。
(2)PC Register 程序计数器
每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向下
一条指令的地址,也即将要执行的指令代码),由执行引擎读取下一条指令,是一个非常小的内存空间,
几乎可以忽略不记。
5.Native Method Stack
它的具体做法是Native Method Stack中登记native方法,在Execution Engine执行时加载本地方法库。
6. 栈
栈也叫栈内存,主管Java程序的运行,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束该栈就Over,生命周期和线程一致,是线程私有的。基本类型的变量、实例方法、引用类型变量都是在函数的栈内存中分配。
栈管运行 堆管存储
Exception in thread "main" java.lang.StackOverflowError
1.1 栈存储什么?
栈帧中主要保存3类数据:
本地变量 (Local Variable) :输入参数和输出参数以及方法内的变量;(输入参数就是形参,输出参数就是返回值)
栈操作 (Operand Stack): 记录出栈入栈的操作;
栈帧数据 (Frame Data):包括类文件,方法等等。
1.2 栈运行原理
栈中的数据都是以栈帧(Stack Frame)的格式存在,栈帧是一个内存区块,是一个数据集,是一个有关方法
(Method)和运行期数据的数据集,当一个方法A被调用时就产生了一个栈帧F1,并被压入栈中,A方法有调用B方法,于是产生栈帧F2也被压入栈中.......。执行完毕后遵循先进后出的方式弹出栈帧。线程结束,栈释放
1.3 栈空间的基本组成单元
栈空间的基本组成单元是栈帧每调用一个方法在栈空间中就会有一个新的栈帧入栈,当方法结束时对应的栈帧就会出栈
深度理解JVM的更多相关文章
- 走进JVM【二】理解JVM内存区域
引言 对于C++程序员,内存分配与回收的处理一直是令人头疼的问题.Java由于自身的自动内存管理机制,使得管理内存变得非常轻松,不容易出现内存泄漏,溢出的问题. 不容易不代表不会出现问题,一旦内存泄漏 ...
- 《深入理解JVM虚拟机》读书笔记
前言:<深入理解JVM虚拟机>是JAVA的经典著作之一,因为内容更偏向底层,所以之前一直没有好好的阅读过.最近因为刚好有空,又有了新目标.所以打算和<构架师的12项修炼>一起看 ...
- 深入理解JVM之JVM内存区域与内存分配
深入理解JVM之JVM内存区域与内存分配 在学习jvm的内存分配的时候,看到的这篇博客,该博客对jvm的内存分配总结的很好,同时也利用jvm的内存模型解释了java程序中有关参数传递的问题. 博客出处 ...
- 《深入理解JVM》第二章读书笔记
Java内存区域与内存溢出异常 运行时数据区域 JVM执行java程序的时候有一个运行时数据区,每个区域有自己的作用,了解这些区域有助于我们理解JVM.JVM运行时数据区如图所示: 程序计数器 该区域 ...
- Java深度理解——Java字节代码的操纵
导读:Java作为业界应用最为广泛的语言之一,深得众多软件厂商和开发者的推崇,更是被包括Oracle在内的众多JCP成员积极地推动发展.但是对于 Java语言的深度理解和运用,毕竟是很少会有人涉及的话 ...
- 深入理解JVM虚拟机11:Java内存异常原理与实践
本文转自互联网,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutori ...
- 深入理解JVM虚拟机1:JVM内存的结构与消失的永久代
本文转自互联网,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutori ...
- 深入理解JVM(学习过程)
这,仅是我学习过程中记录的笔记.确定了一个待研究的主题,对这个主题进行全方面的剖析.笔记是用来方便我回顾与学习的,欢迎大家与我进行交流沟通,共同成长.不止是技术. 2020年02月06日22:43:0 ...
- 从JAVA内存到垃圾回收,带你深入理解JVM
摘要:学过Java的程序员对JVM应该并不陌生,如果你没有听过,没关系今天我带你走进JVM的世界.程序员为什么要学习JVM呢,其实不懂JVM也可以照样写出优质的代码,但是不懂JVM有可能别被面试官虐得 ...
随机推荐
- xv6学习笔记(4) : 进程调度
xv6学习笔记(4) : 进程 xv6所有程序都是单进程.单线程程序.要明白这个概念才好继续往下看 1. XV6中进程相关的数据结构 在XV6中,与进程有关的数据结构如下 // Per-process ...
- Spring系列之多个数据源配置
前言 在上篇文章讲到了如何配置单数据源,但是在实际场景中,会有需要配置多个数据源的场景,比如说,我们在支付系统中,单笔操作(包含查询.插入.新增)中需要操作主库,在批量查询或者对账单查询等对实时性要求 ...
- IDEA远程调试代码
一.设置远程调式端口 点击Remote 设置名字和要部署的远程服务器IP地址和端口 二.将Jar包上传到远程服务器运行 启动命令 java -Xdebug -agentlib:jdwp=transpo ...
- Json序列化更新好友列表
一.概述 使用Newtonsoft.Json开源库进行序列化 二.代码 using Newtonsoft.Json; using System; using System.Collections.Ge ...
- 【转】Java 开发必会的 Linux 命令
转自:https://www.cnblogs.com/zhuawang/p/5212809.html 作为一个Java开发人员,有些常用的Linux命令必须掌握.即时平时开发过程中不使用Linux(U ...
- Go并发控制--Channel篇
目录 1. 前言 2. 使用channel控制子协程 2.1 使用场景 2.2 总结 1. 前言 我们考虑这么一种场景,协程A执行过程中需要创建子协程A1.A2.A3-An,协程A创建完子协程后就等待 ...
- Mybatis原理和代码剖析
参考资料(官方) Mybatis官方文档: https://mybatis.org/mybatis-3/ Mybatis-Parent : https://github.com/mybatis/par ...
- mpvue 生成字节跳动小程序的问题!!
初始化项目文件 $ vue init mpvue/mpvue-quickstart fuck $ cd fuck $ npm install 这个时候就初始化好了,接下来 $ npm run dev: ...
- springboot通过AOP和自定义注解实现权限校验
自定义注解 PermissionCheck: package com.mgdd.sys.annotation; import java.lang.annotation.*; /** * @author ...
- docker数据卷(Data Volumes)
Docker宿主机和容器之间文件拷贝docker copy 前言: Docker 数据管理 在生产环境中使用 Docker ,往往需要对数据进行持久化,或者需要在多个容器之间进行 数据共享,这必然涉及 ...