JVM-概述和内存区域
JVM的优势
Java的跨平台性
一次编译,到处运行
JVM跨语言
举个例子
将groovy编译之后的class文件用jvm运行
先配置好groovy环境
新建HelloWorld.groovy
class HelloWorld {
static main(args) {
println "hello groovy...";
}
}
将其编译成class文件
groovyc HelloWorld.groovy
用java命令运行groovy编译出来的HelloWorld.class文件
(注:全局搜索groovy-all-xxxx.jar的jar包,将其路径作为classpath后的参数)java -classpath "E:\codingEnvironment\IntelliJ IDEA 2019.1.3\lib\groovy-all-2.4.15.jar;." HelloWorld
JVM整体结构
HotSpot VM
方法区和堆区是所有线程共享的内存区域;
Java栈又叫做jvm虚拟机栈。
执行引擎等同于翻译class文件的语言翻译器。
方法区(永久代)在jdk8中又叫做元空间
Metaspace
- 方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器(JIT编译器,英文写作Just-In-Time Compiler)编译后的代码等数据。
- 虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做 Non-Heap(非堆),目的应该是与 Java 堆区分开来。
运行时数据区
概述
堆内存:保存所有引用数据的真实信息;
栈内存:基本类型、运算、指向堆内存的指针;
方法区:所以定义的方法的信息都保存方法区中,属于共享区;
程序计数器:是一个非常小的内存空间,用来保证程序依次执行;
本地方法栈:每一次执行递归方法的时候,都会将上一个方法入栈;
方法区(Method Area)
1. 什么是方法区(Method Area)?
方法区(Method Area)与Java堆一样,是各个线程共享的内存区域。
2.方法区(Method Area)存储什么?
它存储已被Java虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等
域信息(成员变量)和方法信息可以看成在类型信息内
2.1 类信息
对每个加载的类型(类class、接口interface、枚举enum、注解annotation),JVM必须在方法区中存储以下类型信息:
- 这个类型的完整有效名称(全名=包名.类名)
- 这个类型直接父类的完整有效名称(
java.lang.Object
除外,其他类型若没有声明父类,默认父类是Object) - 这个类型的修饰符(
public、abstract、final
的某个子集) - 这个类型直接接口的一个有序列表
除此之外还方法区(Method Area)存储类信息还有 - 类型的常量池( constant pool)
- 域(Field)信息
- 方法(Method)信息
- 除了常量外的所有静态(static)变量
方法区(Method Area)存储类信息请参考:参考博客
2.2 常量
- static final修饰的成员变量都存储于 方法区(Method Area)中
2.3 静态变量
- 静态变量又称为类变量,类中被static修饰的成员变量都是静态变量(类变量)
- 静态变量之所以又称为类变量,是因为静态变量和类关联在一起,随着类的加载而存在于方法区(而不是堆中)
- 八种基本数据类型(byte、short、int、long、float、double、char、boolean)的静态变量会在方法区开辟空间,并将对应的值存储在方法方法区,对于引用类型的静态变量如果未用
new
关键字为引用类型的静态变量分配对象(如:static Object obj;
)那么对象的引用obj会存储在方法区中,并为其指定默认值null
;若,对于引用类型的静态变量如果用new
关键字为引用类型的静态变量分配对象(如:static Person person = new Person();
),那么对象的引用person 会存储在方法区中,并且该对象在堆中的地址也会存储在方法区中(注意此时静态变量只存储了对象的堆地址,而对象本身仍在堆内存中);这个过程还涉及到静态变量初始化问题,可以参考博客:静态变量初始化相关
2.4 方法(Method)
- 程序运行时会加载类编译生成的字节码,这个过程中静态变量(类变量)和静态方法及普通方法对应的字节码加载到方法区。
- 但是!!!方法区中没有实例变量,这是因为,类加载先于对应类对象的产生,而实例变量是和对象关联在一起的,没有对象就不存在实例变量,类加载时没有对象,所以方法区中没有实例变量
- 静态变量(类变量)和静态方法及普通方法在方法区(Method Area)存储方式是有区别的
栈(Stack)
栈(Stack):线程私有的内存区域
- 每个方法(Method)执行时,都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口信息等
- 栈中所存储的变量和引用都是局部的(即:定义在方法体中的变量或者引用),局部变量和引用都在栈中(包括final的局部变量)
- 八种基本数据类型(byte、short、int、long、float、double、char、boolean)的局部变量(定义在方法体中的基本数据类型的变量)在栈中存储的是它们对应的值
- 栈中还存储局部的对象的引用(定义在方法体中的引用类型的变量),对象的引用并不是对象本身,而是对象在堆中的地址,换句话说,局部的对象的引用所指对象在堆中的地址在存储在了栈中。当然,如果对象的引用没有指向具体的对象,对象的引用则是
null
Java堆(Java Heap)
Java堆(Java Heap) :被所有线程共享的一块内存区域,在虚拟机启动时创建。Java堆(Java Heap)唯一目的就是存放对象实例。所有的对象实例及数组都要在Java堆(Java Heap)上分配内存空间。
- 由关键字new产生的所有对象都存储于Java堆(Java Heap)
- !!! 实例变量(非static修饰的成员变量)和对象关联在一起,所以实例变量也在堆中
- java数组也在堆中开辟内存空间
栈、堆和方法区的关系
Java代码大致执行流程
java源程序--编译javac-->字节码文件.class-->类装载子系统生成反射类(存入方法区)--->运行时数据区(五大块儿)--->执行引擎-->解释执行+编译执行(JIT)-->操作系统(Win,Linux,Mac JVM)
作用
将高级语言转化为机器能听得懂的机器指令
Hotspot中方法区的变动
关于方法区的结构,在过去的版本jdk1.6/1.7/1.8当中均有变动,故在此提前声明:
- jdk1.6及之前:有永久代(permanent generation) ,静态变量、字符串常量池存放在 永久代上。
- jdk1.7:有永久代,但已经逐步“去永久代”,字符串常量池、静态变量移除,保存在堆中。注意:
- jdk1.8及之后: 无永久代,类型信息、字段、方法、常量保存在本地内存的元空间,但字符串常量池、静态变量仍留在堆空间.
JDK6
JDK7
注意:
jdk1.8及之后: 无永久代,类型信息、字段、方法、常量保存在本地内存的元空间。
但字符串常量池、静态变量仍留在堆空间。
除此之外,元空间(或称方法区),不再使用虚拟机内存,而是使用本地内存。
JDK8
参考资料
(3条消息)JVM学习笔记(三)------内存管理和垃圾回收_走向架构师之路-CSDN博客
(3条消息)Java虚拟机(JVM)面试题(2020最新版)_ThinkWon的博客-CSDN博客
JVM-概述和内存区域的更多相关文章
- JVM中有哪些内存区域,分别是用来干什么的
前言 之前我们探讨过一个.class文件是如何被加载到jvm中的.但是jvm内又是如何划分内存的呢?这个内被加载到了那一块内存中?jvm内存划分也是面试当中必被问到的一个面试题. 什么是jvm内存区域 ...
- JVM之Java内存区域
JVM之Java内存区域 世界上并没有完美的程序,但我们并不因此而沮丧,因为写程序本来就是一个不断追求完美的过程. 一.JAVA内存区域 谈及JAVA虚拟机运行时数据区域就不得不祭出这张经典的图了: ...
- JVM总结之内存区域
Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,有的区域是线程共享的,有的区域是线程隔离的.如下图: 程序计数器 程序计数器(Progra ...
- 深入理解JVM - 1 - Java内存区域划分
作者:梦工厂链接:https://www.jianshu.com/p/7ebbe102c1ae来源:简书简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处. Java与C++之间有一堵 ...
- JVM运行时内存区域
JVM运行java程序时会将内存划分为若干个不同的数据区域: (1)程序计数器: 1.占用内存空间不大. 2.程序计数器相当于JVM所执行的字节码(jvm指令)的“行号指示器”,通过程序计数器的“值” ...
- 理解JVM之Java内存区域
Java虚拟机运行时数据区分为以下几个部分: 方法区.虚拟机栈.本地方法栈.堆.程序计数器.如下图所示: 一.程序计数器 程序计数器可看作当前线程所执行的字节码行号指示器,字节码解释器工作时就是通过改 ...
- 史上最详细JVM,Java内存区域讲解
本人免费整理了Java高级资料,一共30G,需要自己领取:传送门:https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q 运行时数据区域 JVM载执行Jav ...
- 学习jvm(一)--java内存区域
前言 通过学习深入理解java虚拟机的教程,以及自己在网上的查询的资料,做一个对jvm学习过程中的小总结. 本文章内容首先讲解java的内存分布区域,之后讲内存的分配原则以及内存的监控工具.再下来会着 ...
- JVM:Java内存区域与内存溢出异常
Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁时间,有些区域随着虚拟机进程的启动而存在,有些区域依赖用户线程的启动和 ...
- JVM笔记3-java内存区域之运行时常量池
1.运行时常量池属于线程共享区中的方法区. 2.运行时常量池用于编译期生成的各种自变量,符号引用,这部分内用将在类加载后接入方法区的运行时常量池中存放. 看如下代码所示,如图: public clas ...
随机推荐
- css3新属性position: sticky 一分钟实现 导航栏悬停功能
css3新属性position: sticky 一分钟实现 导航栏悬停功能 前言 正文 前言 想必很多前端小伙伴经常会在开发中遇到这样一个需求,就是在下划时,导航栏悬停在屏幕最上方,例如咱们的csdn ...
- Jmeter 常用函数(18)- 详解 __isDefined
如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.htm 作用 判断 Jmeter 变量是否存在,1 就 ...
- .Net Core中的诊断日志DiagnosticSource讲解
前言 近期由于需要进行分布式链路跟踪系统的技术选型,所以一直在研究链路跟踪相关的框架.作为能在.Net Core中使用的APM,SkyWalking自然成为了首选.SkyAPM-dotnet是 ...
- 要有一颗理财的心 - 读<富爸爸.穷爸爸>
记得工作没多久后的一次加薪的例行谈话.部门经理和我说,不能靠工资过日子,要多想想怎么投资,我的主要财富就是靠投资赚来的.当时第一反应,老板,你不给我加薪找这借口也太牵强了吧.我的收入只有工资,我的工资 ...
- JavaScript学习系列博客_38_JavaScript 事件
事件(Event) - 事件指的是用户和浏览器之间的交互行为.比如:点击按钮.关闭窗口.鼠标移动.... - 我们可以为事件来绑定回调函数来响应事件. - 绑定事件的方式: 1.可以在标签的事件属性中 ...
- 洛谷p1052过河 路径压缩+dp
洛谷 P1052 过河 思路部分可以看这篇博客 我将在这里对其进行一些解释与补充 首先我们先看题 乍一看 这不是模板题吗 然后开开心心的敲了一个简单dp上去 #include<iostream& ...
- koa-graphql express-graphql 中如何 定义每一个字段resolver执行函数
第一种方式: 首先来看一下,官方给出的koa-graphql的例子, ```js var express = require('express'); var {graphqlHTTP} = requ ...
- 《Head First 设计模式》:模板方法模式
正文 一.定义 模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤. 要点: 模板方法定义了一个算法的步骤,每 ...
- 记一个Selenium自动化测试网页
今天想跟大家分享的是Selenium自动化测试网页,就是关于selenium的自动化测试一些基础的东西,如有不对的地方请多多指教. 一.安装环境 1.Python环境 安装完成后通过Windows命令 ...
- 【Android】AndroidStudio打包apk出现的一些问题 `Error:Execution failed for task ':app:lintVitalRelease'.
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985, QQ986945193 公众号:程序员小冰 1,错误代码: `Error:Execution fai ...