当前位置: 首页 > news >正文

JVM——引言+JVM内存结构

引言

什么是JVM

定义:

Java VirtualMachine -java 程序的运行环境 (ava 二进制字节码的运行环境)

好处:

  • 一次编写,到处运行
  • 自动内存管理,垃圾回收功能
  • 数组下标越界检查,
  • 多态

比较:

jvm jre jdk

学习jvm的作用

  • 面试
  • 理解底层实现原理
  • 中高级程序员的必备技能

常见的jvm

自己百度查找

jvm的组成

 内存结构

程序计数器

定义

Program Counter Register 程序计数器(寄存器)

作用

如下图所示

右边就是简单的java代码打印操作,编译成左侧的二进制字节码。

经过解释器——>机器码——>CPU执行。

程序计数器在这里面的作用就是记住下一条jvm指令的执行地址。

第一条指令地址是0,第一条指令交给解释器去执行的同时会把第二条指令的地址3放入程序计数器。第一条执行完之后,解释器会去取出3来执行......

物理实现: 通过CPU中寄存器(速度快)实现

 特点:

线程私有

每个线程都有自己的程序计数器。

每一个线程会有被分配一个时间片,在当前时间片内不能执行完会去执行别的线程的代码,直到轮到下一个时间片。

切换到别的线程时要记住当前执行到哪里,还是要用到程序计数器。通过私有的程序计数器知道下一行代码的地址。

 唯一不会存在内存溢出的区

虚拟机栈

栈是一种普通的先进后出的数据结构。

java的虚拟机栈则是线程运行需要的内存空间

一段代码有多个方法组成,一个栈帧表示一次方法的调用,栈帧就是每个方法运行需要的内存

运行:调用第一个方法时会给第一个方法划分一个栈帧空间,并压入栈内,执行完后会出栈,也会释放该方法占用的内存。

然后方法1调用方法2时会产生一个方法2的栈帧并入栈,然后方法2调用方法3也会产生并入栈,如下图所示。

 定义

Java Virtual Machine Stacks (Java 虚拟机栈)

  • 每个线程运行时所需要的内存,称为虚拟机栈
  • 每个栈由多个栈帧 (Frame) 组成,对应着每次方法调用时所占用的内存
  • 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法 

栈帧大小由方法里的参数以及局部变量的个数决定 

问题辨析

1.垃圾回收是否涉及栈内存?

   栈内存是一次次方法调用产生的栈帧内存,调用结束后会弹出栈,会自动回收,不需要垃圾回收     管理,垃圾回收是回收堆内存中的无用对象。

2.栈内存分配越大越好吗?

运行java代码时是可以指定栈内存大小的,使用-Xss size,下图还有不同系统下默认栈内存的大小和设定内存的示例。

栈内存越大会让线程数变少,512mb的物理内存下,每个线程的栈内存设置1mb大小可以运行512个,设置2mb大小可以运行256个线程。不会提高线程效率,但可以增加递归的层数。

        

3.方法内的局部变量是否线程安全?

        根据该变量是每个线程共享还是线程私有判断。下图是一个方法,方法内有一个局部变量。

该方法被调用两次时会有两个不同的栈。每个线程都会有私有的局部变量。因此这里不会有线程干扰的问题。

 假如将x改为static int x=0;的话就会出现线程干扰,如果不加保护的话会有线程安全问题。

总结:共享需要考虑线程安全,私有就不需要考虑。

  • 如果方法内的局部变量没有逃离方法的作用范围,则是线程安全。
  • 如果是局部变量引用了对象,并逃离方法的作用方法,需要考虑线程安全(引用传递和值传递的问题)

栈内存溢出

  • 栈帧过多导致栈内存溢出(栈帧过多爆栈)  :  通常在的递归导致。
  • 单片栈帧过大导致栈内存溢出(太大了,已经塞满了)

 一般不会有单片过大,栈帧里都是方法参数和局部变量。可以通过设置栈内存大小达到

 在将对象转换成json对象时也会有栈溢出,这种两个类的循环问题会导致json解释器出现问题。

 可以通过一个@JsonIgnore注解达到在json转换对象时忽略变量的效果。 

 

线程运行诊断

案例1: cpu 占用过多

 linux环境下运行一段java代码导致cpu占用过高,可以使用top命令定位到哪一个进程占用,但看不见是哪一个线程导致的。

在linux下使用ps H -eo pid,tid,%cpu 命令可以看见所有线程的pid(进程号),tid(线程号),%cpu(cpu占用)。

使用ps H -eo pid,tid,%cpu | grep 32655   后面加上| grep pid过滤无关进程的线程。

  • 用top定位哪个进程对cpu的占用过高
  • ps H -eo pid,tid,%cpu | grep pid (用ps命令进一步定位是哪个线程引起的cpu占用过高)
  • jstack 进程id  (可以根据线程id 找到有问题的线程,进一步定位到问题代码的源码行号)

生产环境不推荐jstack,因为打印线程信息jvm会暂停其他线程 

然后将线程编号32665转换成16进制(7F99)在输出内容中查找 

 在jstack 输出内容中可以看见一个nid=Ox7f99的线程,状态为RUNNABLE.

看见问题出在第8行代码。如下图源码第8行是个死循环。

 nid、pid 和 tid 是计算机系统中常用的三个标识

  • nid (Node ID) 是指在分布式系统中,每个节点的唯一标识
  • pid (Process ID) 是指操作系统中每个进程的唯一标识。
  • tid (Thread ID) 是指操作系统中每个线程的唯一标识。

案例2: 程序运行很长时间没有结果

线程死锁导致的无结果下使用jstack命令查看,下输出内容最后可以看见有关死锁信息。

 两个线程都想获得a,b,但是都在等对方放开拥有的对象,然后陷入死锁。

产生死锁的四个必要条件:互斥、不可剥夺、请求和保持、循环等待。

本地方法栈

定义:    java虚拟机在调用本地方法时需要给本地方法提供的内存空间

在Object这个类中就有很多,比如Object的clone方法的声明是native,这个native的实现是c/c++,java代码是间接调用native

 

定义

通过 new 关键字,创建对象都会使用堆内存

特点:

  • 它是线程共享的,堆中对象都需要考虑线程安全的问题
  • 有垃圾回收机制 (不再被引用的对象会被回收) 

堆内存溢出

下图所示方法中String类型的对象a会一次次变大,直至堆溢出。

 运行结果:  溢出内存错误: java 堆 空间

使用-Xmx size改变堆空间大小。

 

 修改前26次才溢出,修改后17次溢出。

有可能堆内存较大,运行时间短,在系统前期看不出问题,后期才会爆掉,故测试时可以将堆内存设置较小进行排查。

堆内存诊断

相关工具:

1.jps 工具

        查看当前系统中有哪些 java 进程

2. jmap 工具

        查看堆内存占用情况 jmap -heap 进程id (只能看某一瞬间的情况)

3.jconsole 工具 

        图形界面的,多功能的监测工具,可以连续监测

4.jvisualVM 工具

        图形化界面,可以抓取当前快照 

案例1

 new一个10MB的数组对象,后面置为null,然后gc显式回收。

运行后通过jps查看进程id,jmap -heap 18756在1~2,2~3,3之后三个时间点抓取快照信息。 

最大堆内存占用MaxHeapSize是4个G 

 

Eden Space就是专门为new 出来的对象准备的。 

 1~2之间

数组创建之前使用了6Mb

 2~3之间

创建数组对象之后使用16mb,

 3之后

垃圾回收之后变成1.2mb

使用jconsole工具的界面。

 案例2

垃圾回收之后,内存占用任然很高。

新生代被回收了,老年代没有被回收。

 新生代剩8mb

 老年代剩200mb

使用新的工具jvisualvm可视化虚拟机

 

保存快照之后进行查找最大的类 

 查看最大的ArrayList实例的具体信息

 源代码

两百个Student对象,每个都开了一个1mb大小的byte数组。并且一直在作用范围内,无法回收,内存占用居高不下。

 通过可视化界面的堆 dump按钮进行排查。 

方法区

定义

按照jdk_jvm_1.8中的定义

  • 方法区是所有java虚拟区线程共享的区域。
  • 存储了和类的结构相关的信息。
  • 有成员变量filed,method data方法数据,成员方法、构造器方法的代码以及运行时常量值run-time constant pool等等
  • 在虚拟机启动时被创建
  • 逻辑上是堆的组成部分(1.8以前用的堆内存,1.8以后用的是系统内存
  • 方法区也会导致内存溢出

组成

永久代和元空间都是方法区这个概念的实现。

永久代和元空间最本质的区别就是 前者使用的是jvm内存 后者使用的是操作系统内存。

图中常量池是运行时常量池。

 方法区内存溢出

  • 1.8 以前会导致永久代内存溢出
  • 1.8 之后会导致元空间内存溢出

下图代码就是一个加载了10000个类的代码,最外层继承实现了类加载器,在循环内指定版本号,类名,包名,父类,接口等信息创建一个新类。

这里元空间和永久代都没有设置上限,这里需要设置元空间和永久代大小。

-XX:MaxMetaspaceSize=8m  元空间

-XX:MaxPermSize=8m  永久代

元空间运行报异常 

 永久代报异常

 场景:

  • spring
  • mybatis

spring和mybatis都使用到了cglib技术。

运行时常量池

下面的这段代码的二进制字节码含有如下信息。 

使用如下命令查看该代码反编译后的结果

javap -v HelloWorld.class

常量池部分

 虚拟机指令部分

执行指令时下面第一条就是获取静态变量,#2在常量池里面找。

ldc是找到一个引用地址。

 定义:

  • 常量池,就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息
  • 运行时常量池,常量池是*.class 文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址

 运行时常量池里面#1,#2...这些会变成内存地址。

相关文章:

JVM——引言+JVM内存结构

引言 什么是JVM 定义: Java VirtualMachine -java 程序的运行环境 (ava 二进制字节码的运行环境) 好处: 一次编写,到处运行自动内存管理,垃圾回收功能数组下标越界检查,多态 比较: jvm jre jdk 学习jvm的作用 面试理解底层实现原理中…...

open cv学习 (十)图形检测

图形检测 demo1 # 绘制几何图像的轮廓 import cv2img cv2.imread("./shape1.png")gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 将图像二值化 t, binary cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)# 检测图像中的所有轮廓 contours, hierarchy cv2.f…...

【C语言】字符函数和字符串函数

目录 1.求字符串长度strlen 2.长度不受限制的字符串函数 字符串拷贝strcpy 字符串追加strcat 字符串比较strcmp 3.长度受限制的字符串函数介绍strncpy strncat ​编辑strncmp 4.字符串查找strstr 5.字符串分割strtok 6.错误信息报告 strerror perror 7.字符分类函…...

前馈神经网络正则化例子

直接看代码: import torch import numpy as np import random from IPython import display from matplotlib import pyplot as plt import torchvision import torchvision.transforms as transforms mnist_train torchvision.datasets.MNIST(root…...

spring的核心技术---bean的生命周期加案例分析详细易懂

目录 一.spring管理JavaBean的初始化过程(生命周期) Spring Bean的生命周期: 二.spring的JavaBean管理中单例模式及原型(多例)模式 2.1 . 默认为单例,但是可以配置多例 2.2.举例论证 2.2.1 默认单例 2.2…...

【Maven教程】(一)入门介绍篇:Maven基础概念与其他构建工具:理解构建过程与Maven的多重作用,以及与敏捷开发的关系 ~

Maven入门介绍篇 1️⃣ 基础概念1.1 构建1.2 maven对构建的支持1.3 Maven的其他作用 2️⃣ 其他构建工具2.1 IDE2.2 Make2.3 Ant2.4 Jenkins 3️⃣ Maven与敏捷开发🌾 总结 1️⃣ 基础概念 "Maven"可以翻译为 “知识的积累者” 或 “专家”。这个词源于波…...

今天,谷歌Chrome浏览器部署抗量子密码

谷歌已开始部署混合密钥封装机制(KEM),以保护在建立安全的 TLS 网络连接时共享对称加密机密。 8月10日,Chrome 浏览器安全技术项目经理Devon O’Brien解释说,从 8 月 15 日发布的 Chrome 浏览器 116 开始,谷…...

SUMO traci接口控制电动车前往充电站充电

首先需要创建带有停车位的充电站(停车场和充电站二合一),具体参考我的专栏中其他文章。如果在仿真的某个时刻,希望能够控制电动车前往指定的充电站充电,并且在完成充电后继续前往车辆原来的目的地,那么可以使用以下API&#xff1a…...

现代CSS中的换行布局技术

在现代网页设计中,为了适应不同屏幕尺寸和设备类型,换行布局是一项重要的技术。通过合适的布局技术,我们可以实现内容的自适应和优雅的排版。本文将介绍CSS中几种常见的换行布局技术,探索它们的属性、代码示例和解析,帮…...

简单理解Python中的深拷贝与浅拷贝

I. 简介 深拷贝会递归的创建一个完全独立的对象副本,包括所有嵌套的对象,而浅拷贝只复制嵌套对象的引用,不复制嵌套对象本身。 简单来说就是两者都对原对象进行了复制,因此使用is运算符来比较新旧对象时,返回的都是F…...

C++之std::pair<uint64_t, size_t>应用实例(一百七十七)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...

前端打开后端返回的HTML格式的数据

前端打开后端返回的 HTML格式 的数据: 后端返回的数据格式如下示例: 前端通过 js 方式处理(核心代码如下) console.log(回调, path); // path 是后端返回的 HTML 格式数据// 必须要存进localstorage,否则会报错&am…...

How to deal with document-oriented data

Schema designData models for e-commerceNuts and bolts of databases, collection, and documents. Principles of schema design What are your application access pattern?Whats the basic unit of data? the basic unit of data is the BSON documentWhat are the ca…...

Http 状态码汇总

文章目录 Http 状态码汇总1xx(信息性状态码)2xx(成功状态码)3xx(重定向状态码)4xx(客户端错误状态码)5xx(服务器错误状态码) Http 状态码汇总 1xx&#xff08…...

mysql自定义实体类框架

根据表结构自动生产实体类和方法,根据反射与io生成,可自定义扩展方法 package com.digital.web.front; /*** pom依赖* <dependency>* <groupId>mysql</groupId>* <artifactId>mysql-connector-java</artifactId>* <version>5.1.27</ve…...

批量将Excel中的第二列内容从拼音转换为汉字

要批量将Excel中的第二列内容从拼音转换为汉字&#xff0c;您可以使用Python的openpyxl库来实现。下面是一个示例代码&#xff0c;演示如何读取Excel文件并将第二列内容进行拼音转汉字&#xff1a; from openpyxl import load_workbook from xpinyin import Pinyin # 打开Exce…...

消息推送:精准推送,提升运营效果,增添平台活力

对于app开发者而言&#xff0c;没有什么途径比消息推送更能直接、即时地触及目标用户群体了。消息推送与我们的日常生活息息相关&#xff0c;各种APP的状态和通知都通过消息推送来告知用户&#xff0c;引起用户的注意&#xff0c;吸引用户点开app。总而言之&#xff0c;推送服务…...

[保研/考研机试] KY43 全排列 北京大学复试上机题 C++实现

题目链接&#xff1a; 全排列https://www.nowcoder.com/share/jump/437195121692001512368 描述 给定一个由不同的小写字母组成的字符串&#xff0c;输出这个字符串的所有全排列。 我们假设对于小写字母有a < b < ... < y < z&#xff0c;而且给定的字符串中的字…...

Java将时间戳转化为特定时区的日期字符串

先上代码&#xff1a; ZonedDateTime dateTime ZonedDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()),zone ); //2019-12-01T19:01:4608:00String formattedDate dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd") ); //2019-12-…...

【算法挨揍日记】day03——双指针算法_有效三角形的个数、和为s的两个数字

611. 有效三角形的个数 611. 有效三角形的个数https://leetcode.cn/problems/valid-triangle-number/ 题目描述&#xff1a; 给定一个包含非负整数的数组 nums &#xff0c;返回其中可以组成三角形三条边的三元组个数。 解题思路&#xff1a; 本题是一个关于三角形是否能成立…...

通过 kk 创建 k8s 集群和 kubesphere

官方文档&#xff1a;多节点安装 确保从正确的区域下载 KubeKey export KKZONEcn下载 KubeKey curl -sfL https://get-kk.kubesphere.io | VERSIONv3.0.7 sh -为 kk 添加可执行权限&#xff1a; chmod x kk创建 config 文件 KubeSphere 版本&#xff1a;v3.3 支持的 Kuber…...

感觉和身边其他人有差距怎么办?

虽然清楚知识需要靠时间沉淀&#xff0c;但在看到自己做不出来的题别人会做&#xff0c;自己写不出的代码别人会写时还是会感到焦虑怎么办&#xff1f; 你是否也因为自身跟周围人的差距而产生过迷茫&#xff0c;这份迷茫如今是被你克服了还是仍旧让你感到困扰&#xff1f; 下…...

【C语言基础】宏定义的用法详解

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…...

微服务系列文章之 SpringBoot 最佳实践

Spring Boot 是一种广泛使用且非常流行的企业级高性能框架。 以下是一些最佳实践和一些技巧&#xff0c;我们可以使用它们来改进 Spring Boot 应用程序并使其更加高效。 Spring Boot 的四大核心 1、自动配置 针对很多Spring应用程序和常见的应用功能&#xff0c;Spring Boo…...

C++并发多线程--std::async、std::packaged_task和std::promise的使用

目录 1--std::async的使用 2--std::packaged_task的使用 3--std::promise的使用 1--std::async的使用 std::async用于启动一个异步任务&#xff0c;并返回一个std::future对象&#xff1b;std::future对象里含有异步任务线程入口函数的结果&#xff1b; std::launch::deferr…...

opencv-目标追踪

import argparse import time import cv2 import numpy as np# 配置参数 ap argparse.ArgumentParser() ap.add_argument("-v", "--video", typestr,help"path to input video file") ap.add_argument("-t", "--tracker", …...

【数据结构】 单链表面试题讲解

文章目录 引言反转单链表题目描述示例&#xff1a;题解思路代码实现&#xff1a; 移除链表元素题目描述&#xff1a;示例思路解析&#xff1a; 链表的中间结点题目描述&#xff1a;示例&#xff1a;思路解析代码实现如下&#xff1a; 链表中倒数第k个结点题目描述示例思路解析&…...

C++ string类的模拟实现

模拟实现string类不是为了造一个更好的轮子&#xff0c;而是更加理解string类&#xff0c;从而来掌握string类的使用 string类的接口设计繁多&#xff0c;故而不会全部涵盖到&#xff0c;但是核心的会模拟实现 库中string类是封装在std的命名空间中的&#xff0c;所以在模拟…...

Qt实现简单的漫游器

文章目录 Qt的OpenGL窗口GLSL的实现摄像机类的实现简单的漫游器 Qt的OpenGL窗口 Qt主要是使用QOpenGLWidget来实现opengl的功能。  QOpenGLWidget 提供了三个便捷的虚函数&#xff0c;可以重载&#xff0c;用来重新实现典型的OpenGL任务&#xff1a; paintGL&#xff1a;渲染…...

【c语言】文件操作

朋友们&#xff0c;大家好&#xff0c;今天分享给大家的是文件操作的相关知识&#xff0c;跟着我一起学习吧&#xff01;&#xff01; &#x1f388;什么是文件 磁盘上的文件是文件。 但是在程序设计中&#xff0c;我们一般谈的文件有两种&#xff1a;程序文件、数据文件 程序文…...