JVM内存结构

一、 整体结构

.java文件被javac编译成.class字节码文件。

.class文件再由JVM编译成设用于具体系统的机器码文件

下图即JVM编译.class文件的过程

JVM分为 类加载器, 内存结构, 执行引擎三部分

一、类加载器负责加载二进制字节码文件

二、方法区存储类, 具体的类对象实例存储在堆中,栈中存放堆中对象的引用地址, 当类对象调用方法 则会在栈中调用虚拟机栈, 程序技术器(找下一步要执行的JVM指令),本地方法栈中

三、解释器 逐行解释字节码文件

        即时编译器 热点代码不需要重复编译直接存起来

        垃圾回收 释放内存

重点介绍内存结构 

二、程序计数器

右侧是Java源代码, 左侧是.class文件的二进制字节码 也就是JVM指令

字节码需要按行执行, 但执行地址不是有序的

因此, 程序计数器就负责记录下一条JVM指令的执行地址,让解释器直接找到

特点: 每个线程都有自己的程序计数器, 线程私有

            不存在内存溢出 

三、虚拟机栈

1、介绍

虚拟机栈和程序计数器一样, 也是线程私有的, 即线程运行需要开辟一块内存空间-->栈

栈帧:栈会在栈上为线程中每个方法的都分配一块空间, 成为栈帧

方法执行完栈帧释放, 线程执行完栈释放

 

每个虚拟栈默认分配1024KB大小内存, 也可以通过参数指定

 

1. 不涉及 线程执行完栈内存自动没了  GC主要涉及堆

2. 不是 太大线程数量就会受限了

3.  那得看变量是线程共享还是线程私有

        因为方法局部变量主要存储在虚拟机栈中的栈帧上, 每个栈都属于单个线程, 理论上讲是线程安全, 比如基本数据类型的创建和销毁都是在栈帧上,没有问题

        但当局部变量是类的实例对象就不一样了, 栈帧中只是存放对象的引用, 具体对象还是在堆上,这就不是线程安全的了

2、栈溢出

栈空间就那些, 创建太多栈帧导致不够用了 (无线嵌套)

3、线程诊断

案例一、 cpu占用过多

nohup 执行Java程序

top 查看后台进程对CPU的使用情况

通过top命令查出哪个进程对CPU占用较多, 但我们还需要定位到具体线程

可以通过ps打印线程信息,  H 代表所有线程,  -eo 代表只需要获取指定信息  | grep 32655 只需要获取这个进程的全部线程信息

(3)那为了去查看32665线程的具体信息, 还通过jstack 进一步查看

 

找到32665线程 看到 是第8行代码出现问题 问题解决 

回到代码中第8行原来是死循环, CPU占用太多了 

 

案例二、长时间没有结果

 

死锁了

四、本地方法栈

给本地方法运行提供内存空间, 本地方法都是拿C写的 很高级 

 五、堆

1、介绍

通过new 创建对象实例, 都会使用堆内存

  特点: 因为是线程共享的, 所以要考虑线程安全问题

                有垃圾回收问题

2、堆内存溢出

3、堆内存诊断

jconsole作为图形界面查看堆内存使用 , 更直观

五、 方法区

1.定义

两代JVM方法区的区别:

1.6代 : 方法区还在JVM内存中分配,     1.8方法区交给本地内存

1.6代 由永久代实现,                               1.8由元空间实现

1.6 StringTable 被放在常量池中                1.8转移到 堆内存中存储 

2、方法区内存空间溢出

加载类太多了

 

3. 常量池 

        首先需要说明JVM内存结构中的常量池指的是运行时常量池, 因为在.class文件中包含了一张常量池的表, 常量池表中存放Java源代码的各种信息  已加载的类型(每一个class文件中),都维护着一个常量池(不同于方法区的运行时常量池),里面存放着编译时期前就存在的字面值(基本数据类型String、对应的值hello world、及final修饰的变量)和符号引用(对类型、域、方法的引用);这个常量池的内容在类加载的时候,被复制到方法区的运行时常量池;池中的数据项类似数组项一样,是通过索引访问的。

4. class信息

对每个加载的类型,jvm必须在方法区中存储以下类型信息:
1.类的完整有效名;
2.直接父类的完整有效名(除非当前类型是Interface 或 java.lang.Object,两者都没有父类);
3.类型的修饰符(public,abstract, final等);

总结来说就是一个类上户口,需要知道这个类的名字叫什么、父亲是谁、有没有实现接口、 权限是什么。
 

5. 类加载器

jvm必须知道当前.class文件是由启动加载器加载的还是由用户类加载器加载的,如果一个类型是由用户类加载器加载的,那么jvm会将这个类加载器的一个引用作为类型信息的一部分保存在方法区中。

jvm在动态链接的时候需要这个信息,当解析一个类型到另一个类型的引用的时候,jvm需要保证这两个类型的类加载器是相同的,这对jvm区分名字空间的方式是至关重要的。

6、 类变量

由static修饰的变量, 这个不多说, 静态变量随着类加载而放在方法区中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/191919.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

反序列化漏洞(二)

目录 pop链前置知识,魔术方法触发规则 pop构造链解释(开始烧脑了) 字符串逃逸基础 字符减少 字符串逃逸基础 字符增加 实例获取flag 字符串增多逃逸 字符串减少逃逸 延续反序列化漏洞(一)的内容 pop链前置知识,魔术方法触…

【Excel/Matlab】绘x-y图并求切线和截距(详细图解)

最近做大物实验数据较多,手绘图比较麻烦且不精确,所以开始用电脑作图,粗浅记录一下。 方法一 excel (简单快捷) 1 录入数据 在excel中录入数据 2 生成平滑线散点图 选中录入的所有数据->右键点击快速分析->选择…

TCP_握手+挥手过程状态变化分析

TCP状态解读 握手挥手过程状态变化 同时握手 双发同时发起syn请求,状态变化过程如下: 图片来源:http://www.tcpipguide.com/free/t_TCPConnectionEstablishmentProcessTheThreeWayHandsh-4.htm 同时挥手 4次挥手,可以理解为2…

Linux的权限(一)

目录 权限的本质 Linux权限的概念 如何创建与删除普通用户 创建普通用户: 设置用户密码: 删除普通用户: 删除与该用户关联的主目录和邮件目录 : su指令 sudo指令 Linux权限管理 Linux中文件访问者有三种“人” Linux…

使用 Go 构建高性能的命令行工具

命令行工具(CLI)在软件开发中扮演着重要的角色,尤其是在自动化工具、开发工具链和服务器管理等领域。Go 语言以其简洁性和高性能而闻名,非常适合用来创建强大且高效的 CLI 工具。本文将详细介绍如何使用 Go 语言来构建 CLI 应用&a…

甄知黄建华:从“天赋平平”到IT行业“六边形战士”,探索出企业数智化转型的“强IT”之路

本期我们先抛开人物和主体不表,从大环境开始谈起。随着科技的快速发展和全球商业环境的不断变化,中国企业对灵活性、创新性、全球化和效率的需求是迫切的,进行数字化转型来支撑企业的业务变革、组织优化已是业界共识。如何根据企业的实际情况…

锐捷EWEB网管系统 RCE漏洞复现

0x01 产品简介 锐捷网管系统是由北京锐捷数据时代科技有限公司开发的新一代基于云的网络管理软件,以“数据时代创新网管与信息安全”为口号,定位于终端安全、IT运营及企业服务化管理统一解决方案。 0x02 漏洞概述 Ruijie-EWEB 网管系统 flwo.control.ph…

定时任务特辑 | Quartz、xxl-job、elastic-job、Cron四个定时任务框架对比,和Spring Boot集成实战

专栏集锦,大佬们可以收藏以备不时之需: Spring Cloud 专栏:http://t.csdnimg.cn/WDmJ9 Python 专栏:http://t.csdnimg.cn/hMwPR Redis 专栏:http://t.csdnimg.cn/Qq0Xc TensorFlow 专栏:http://t.csdni…

Docker从入门到实战:Docker快速部署、Dockerfile编写、容器间通信及共享数据实战、Docker-compose详解

文章目录 一、基本概念1、体系结构2、容器与镜像1&#xff09;镜像2&#xff09;容器a、容器内部结构b、容器生命周期 3、执行流程 二、常用命令docker pull 镜像名<:tags> &#xff1a;从远程仓库抽取镜像docker images&#xff1a;查看本地镜像docker run 镜像名<:t…

C++11入门

目录 C11简介 统一的列表初始化 声明 范围for循环 STL中一些变化 C11简介 在2003年C标准委员会提交了一份技术勘误表(简称TC1).使得C03这个名字取代了C98成为C11之前的最新C标准名称.但由于C03主要是对C98标准中的漏洞进行修复,语言的核心部分则没有改动,因此人们习惯的把…

代数学笔记6: 群同态基本定理,循环群结构定理

群同态 ρ : G 1 ( , ⋅ ) → G 2 ( , ∘ ) g ↦ ρ ( g ) \rho:G_1(\ ,\cdot)\to G_2(\ ,\circ)\\ \qquad\ \ g\mapsto \rho(g) ρ:G1​( ,⋅)→G2​( ,∘) g↦ρ(g) ∀ g 1 , g 2 ∈ G \forall g_1,g_2\in G ∀g1​,g2​∈G, 有 ρ ( g 1 ⋅ g 2 ) ρ ( g 1 ) ∘ ρ ( g 2 …

解决报错:error: (-215:Assertion failed) inv_scale_x > 0 in function ‘cv::resize‘

需求背景 欲使用opencv的resize函数将图像沿着纵轴放大一倍&#xff0c;即原来的图像大小为(384, 512), 现在需要将图像放大为(768, 512)。 源码 import cv2 import numpy as np# 生成初始图像 img np.zeros((384, 512), dtypenp.uint8) img[172:212, 32:-32] 255 H, W …

卷积神经网络-3D医疗影像识别

文章目录 一、前言二、前期工作1. 介绍2. 加载和预处理数据 二、构建训练和验证集三、数据增强四、数据可视化五、构建3D卷积神经网络模型六、训练模型七、可视化模型性能八、对单次 CT 扫描进行预测 一、前言 我的环境&#xff1a; 语言环境&#xff1a;Python3.6.5编译器&a…

题目:DNA序列修正(蓝桥OJ 3904)

题目描述&#xff1a; 解题思路&#xff1a; 从左到右扫描第一条 DNA 序列和第二条 DNA 序列的每一个位置&#xff0c;检查它们是否互补。 如果某个位置不互补&#xff0c;我们需要寻找第二条 DNA 序列中后续位置的碱基&#xff0c;看是否可以通过交换使这两个位置都互补。如果…

〖大前端 - 基础入门三大核心之JS篇㊹〗- DOM事件委托

说明&#xff1a;该文属于 大前端全栈架构白宝书专栏&#xff0c;目前阶段免费&#xff0c;如需要项目实战或者是体系化资源&#xff0c;文末名片加V&#xff01;作者&#xff1a;不渴望力量的哈士奇(哈哥)&#xff0c;十余年工作经验, 从事过全栈研发、产品经理等工作&#xf…

ssl下载根证书和中间证书

为了保证客户端和服务端通过HTTPS成功通信&#xff0c;您在安装SSL证书时&#xff0c;也需要安装根证书和中间证书。本文介绍如何获取根证书和中间证书。 使用说明 如果您的业务用户通过浏览器访问您的Web业务&#xff0c;则您无需关注根证书和中间证书&#xff0c;因为根证书…

ELK高级搜索,深度详解ElasticStack技术栈-下篇

前言&#xff1a;ELK高级搜索&#xff0c;深度详解ElasticStack技术栈-上篇 14. search搜索入门 14.1. 搜索语法入门 14.1.1 query string search 无条件搜索所有 GET /book/_search结果&#xff1a; {"took" : 969,"timed_out" : false,"_shar…

力扣66. 加一

文章目录 力扣66. 加一示例代码实现总结收获 力扣66. 加一 示例 代码实现 class Solution {public int[] plusOne(int[] digits) {int ndigits.length;for(int in-1;i>0;i--){if(digits[i]!9){digits[i];for(int ji1;j<n;j){digits[j]0;}return digits;}}int[] resnew i…

python+Appium自动化:python多线程多并发启动appium服务

Python启动Appium 服务 使用Dos命令或者bat批处理来手动启动appium服务&#xff0c;启动效率低下。如何将启动Appium服务也实现自动化呢&#xff1f; 这里需要使用subprocess模块&#xff0c;该模块可以创建新的进程&#xff0c;并且连接到进程的输入、输出、错误等管道信息&…

oj塞氪算法练习

向量点积计算 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);int n scanner.nextInt();int[] a new int[n];int[] b new int[n];for (int i 0; i < n; i) {a[i] scanner.nextInt();}…