JVM基础解析(一)

Java里面有 JDK ,JRE, JVM ,这三者的关系是怎么样的呢?

JDK是编译时环境: 整个Java的核心,包括了Java运行环境JRE、Java工具和Java基础类库

JRE是运行时环境: Java virtual machine(JVM),runtime class libraries和Java application launcher

JVM是运行时环境:整个Java实现跨平台的最核心的部分,所有的Java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。

JDK包含JRE,JRE包含JVM。

关系如下图:

JVM解析

JVM内存结构如下图:(绿色标记的堆与方法区为线程共享区,所有线程安全问题都是从这儿引发的; 黄色标记区为线程独享区,和线程安全问题无关

程序计数器(Program Counter),Java堆(Heap),Java虚拟机栈(Stack),本地方法栈(Native Stack),方法区(Method Area)

>> 程序计数器(Program Counter)

  主要执行指令

  每个Java类编译后都会生成一个 *.class文件,例如我定义一个 App.java类,内容如下:

  App.java

package com.imodule.dataImport;

public class App {

	public int add(){
int a = 11;
int b = 22;
int c = (a+b)*10;
return c;
} public static void main(String[] args) {
App app = new App();
int result = app.add();
System.out.println("result = "+result);
} }

  生成的对应的App.class文件内容如下:(这些内容我们看不懂哈哈哈哈,所以下面会使用javap命令来分解)

  App.class

漱壕   4 ;

 # $
#
% & ' (
# )
*
+
,
- . / <init> ()V Code LineNumberTable LocalVariableTable this Lcom/imodule/dataImport/App; add ()I a I b c main ([Ljava/lang/String;)V args [Ljava/lang/String; app result
SourceFile App.java com/imodule/dataImport/App 0 1 2 java/lang/StringBuilder result = 3 4 3 5 6 7 8 9 : java/lang/Object java/lang/System out Ljava/io/PrintStream; append -(Ljava/lang/String;)Ljava/lang/StringBuilder; (I)Ljava/lang/StringBuilder; toString ()Ljava/lang/String; java/io/PrintStream println (Ljava/lang/String;)V !
/ *?? c <=`
h>?
*
q '?Y?L+?=??Y?? ?
??? & '
! "

   我们在windows打开cmd命令窗口,进入App.class文件存在的目录。(我的目录在这里: dataImport\target\classes\com\imodule\dataImport\App.class ,其中开始的 dataImport是我的项目名)

     使用命令 javap -c App ,就会在下方输出指令信息

 

  我们可以用一个文件接收输出内容 ,这里将内内容存储在同级目录的 App.txt下

 

  最后 Apptxt文件中就会出现 程序计数器需要执行的指令啦(我们会发现指令是按大小顺序排列的,但是不是递增的)

  App.txt

Compiled from "App.java"
public class com.imodule.dataImport.App {
public com.imodule.dataImport.App();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return public int add();
Code:
0: bipush 11
2: istore_1
3: bipush 22
5: istore_2
6: iload_1
7: iload_2
8: iadd
9: bipush 10
11: imul
12: istore_3
13: iload_3
14: ireturn public static void main(java.lang.String[]);
Code:
0: new #2 // class com/imodule/dataImport/App
3: dup
4: invokespecial #3 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4 // Method add:()I
12: istore_2
13: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
16: new #6 // class java/lang/StringBuilder
19: dup
20: invokespecial #7 // Method java/lang/StringBuilder."<init>":()V
23: ldc #8 // String result =
25: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: iload_2
29: invokevirtual #10 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
32: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
35: invokevirtual #12 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
38: return
}

 这里我们就来讲一下指令, add()方法里面的指令执行过程:

public int add();
Code:
0: bipush 11   # 将常量 11 压入栈中 (当int取值-1~5采用iconst指令,取值-128~127采用bipush指令,取值-32768~32767采用sipush指令,取值-2147483648~2147483647采用 ldc 指令。)
2: istore_1    # 将数值 11 从操作栈中取出,存储到局部变量 a
3: bipush 22  # 将常量 22 压入栈中
5: istore_2  # 将数值 22 从操作栈中取出,存储到局部变量 b
6: iload_1   # 将局部变量 a 加载到操作栈
7: iload_2   # 将局部变量 b 加载到操作栈
8: iadd  # 执行加运算  局部变量a+b, 结果为33
9: bipush 10 # 将常量10压入栈
11: imul  # 执行乘运算,(a+b)*10,结果为 330
12: istore_3 # 将计算结果 330从栈中取出,存储到局部变量 c
13: iload_3 # 将局部变量 c 加载到操作栈
14: ireturn # 将结果值返回

>>Java堆(Heap) 先进先出

  存储对象

  实例变量、new出来的对象、数组等信息

  关于JVM内存的分配图:(其中永久代为方法区)

  堆内存中垃圾回收机制回收过程分析~

  首先对象会存储堆内存的 年轻代的 Eden区,

  进行垃圾回收后 存活的对象会移到 Survivor 去的 From, (From 和 To会一直有一个空间为空,用于来回复制存活对象 大概移动15~16次)

  存活的对象会进入老年代

  

  关于GC:

  虚拟机在进行MinorGC(新生代的GC)的时候,会判断要进入OldGeneration区域对象的大小,是否大于Old Generation剩余空间大小,如果大于就会发生Full GC。

  刚分配对象在Eden中,如果空间不足尝试进行GC,回收空间,如果进行了MinorGC空间依旧不够就放入Old Generation,如果OldGeneration空间还不够就OOM了。

  虚拟机中存在三种垃圾回收现象,minor GC、major GC和full GC。对新生代进行垃圾回收叫做minor GC,对老年代进行垃圾回收叫做major GC,同时对新生代、老年代和永久代进行垃圾回收叫做full GC。

>>Java虚拟机栈(Stack) 后进先出 First in last out

  存储栈帧

  栈帧包括 局部变量表、操作栈、动态链接、方法出口

  方法存储在栈里面,一个方法对应一个栈帧。

  递归方法,就是自己调用自己,会有N个栈帧存储在栈中,且都符合后进先出的规则。 如果是个死循环就会出现栈溢出: Stackoverflow ................

>>本地方法栈(Native Stack)

  JNI(Java Native Interface)

  本地方法栈,使用native修饰的方法,是指Java调用非Java代码的接口,方法是由非Java语言实现。

  DLL(Dinamic Link Library): 动态链接库文件

>>方法区(Method Area)

 主要存放已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据

(比如spring 使用IOC或者AOP创建bean时,或者使用cglib,反射的形式动态生成class信息等)。

ProcessOn绘图工具地址: https://www.processon.com/diagraming/5d254c70e4b0fdb331d8fa9e

JVM基础详解的更多相关文章

  1. Dom探索之基础详解

    认识DOM DOM级别 注::DOM 0级标准实际并不存在,只是历史坐标系的一个参照点而已,具体的说,它指IE4.0和Netscape Navigator4.0最初支持的DHTML. 节点类型 注:1 ...

  2. [转]JVM指令详解(上)

    作者:禅楼望月(http://www.cnblogs.com/yaoyinglong) 本文主要记录一些JVM指令,便于记忆与查阅. 一.未归类系列A 此系列暂未归类. 指令码    助记符      ...

  3. Android中Canvas绘图基础详解(附源码下载) (转)

    Android中Canvas绘图基础详解(附源码下载) 原文链接  http://blog.csdn.net/iispring/article/details/49770651   AndroidCa ...

  4. javaScript基础详解(1)

    javaScript基础详解 首先讲javaScript的摆放位置:<script> 与 </script> 可以放在head和body之间,也可以body中或者head中 J ...

  5. Python学习一:序列基础详解

    作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/7858473.html 邮箱:moyi@moyib ...

  6. Python学习二:词典基础详解

    作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/7862377.html 邮箱:moyi@moyib ...

  7. JVM内存详解-阅读笔记

  8. 深入浅出DOM基础——《DOM探索之基础详解篇》学习笔记

    来源于:https://github.com/jawil/blog/issues/9 之前通过深入学习DOM的相关知识,看了慕课网DOM探索之基础详解篇这个视频(在最近看第三遍的时候,准备记录一点东西 ...

  9. 三剑客基础详解(grep、sed、awk)

    目录 三剑客基础详解 三剑客之grep详解 1.通配符 2.基础正则 3.grep 讲解 4.拓展正则 5.POSIX字符类 三剑客之sed讲解 1.sed的执行流程 2.语法格式 三剑客之Awk 1 ...

随机推荐

  1. datatable的dom配置

    l - Length changing 改变每页显示多少条数据的控件 f - Filtering input 即时搜索框控件 t - The Table 表格本身 i - Information 表格 ...

  2. poi创建excel文件

    package com.mozq.sb.file01.test; import org.apache.poi.hssf.usermodel.*; import org.apache.poi.hssf. ...

  3. 【使用篇二】SpringBoot使用Druid作为数据源(19)

    Druid是一个关系型数据库连接池,它是阿里巴巴的一个开源项目.Druid支持所有JDBC兼容数据库,包括了Oracle.MySQL.PostgreSQL.SQL Server.H2等.Druid在监 ...

  4. 批量群发,营销必备!Python代码实现自动发送邮件!

    在运维开发中,使用 Python 发送邮件是一个非常常见的应用场景.今天一起来探讨一下,GitHub 的大牛门是如何使用 Python 封装发送邮件代码的. 一般发邮件方法 SMTP是发送邮件的协议, ...

  5. spring-db-事务

    --都是之前各位大佬总结好的,我只是肤浅的汇总一下,结合我犯得错误,适合像我一样的萌新看 第一:@Transcation 引入的注解 package org.springframework.trans ...

  6. Charles 使用笔记

     一.介绍 Charles 属于抓包软件. Charles 多平台支持,mac.windows.linux. Charles 是收费软件,可以免费试用 30 天.试用期过后,未付费的用户仍然可以继续使 ...

  7. Flutter学习一

    包管理 依赖本地包 dependencies: pkg1: path: ../../code/pkg1 依赖git包 dependencies: pkg1: git: url: git://githu ...

  8. 中文版 Apple 官方 Swift 教程《The Swift Programming Language》

    简介 欢迎使用 Swift 关于 Swift 版本兼容性 Swift 初见 Swift 版本历史记录 Swift 教程 基础部分 基本运算符 字符串和字符 集合类型 控制流 函数 闭包 枚举 类和结构 ...

  9. NFS共享储存

    目录 NFS 为什么要使用共享存储 集群没有共享存储的情况 集群有共享存储 NFS的工作原理 NFS部署 1.环境准备 2.关闭防火墙和selinux 3.部署nfs服务端 4.启动rpcbind 5 ...

  10. SQL Server通过定义函数返回字段数据列表模板-干货

    CREATE FUNCTION [dbo].[GetReportDWCustomerOrder] (      @YearDate DATETIME,    参数条件.....    @Categor ...