Java程序运行原理分析

Wesley13
• 阅读 529

class文件内容

  • class文件包含Java程序执行的字节码
  • 数据严格按照格式紧凑排列在class文件的二进制流,中间无分割符
  • 文件开头有一个0xcafebabe(16进制)特殊的标志

Java程序运行原理分析

JVM运行时数据区

Java程序运行原理分析

线程独占: 每个线程都会有它独立的空间,随线程的生命周而创建和销毁

线程共享: 所有线程都能访问这块内存数据,随虚拟机或GC而创建和销毁

方法区

  • 方法区是各个线程共享的内存区域
  • 用于存储已被虚拟机加载的类信息, 常量,静态变量, 即时编译后的代码等数据
  • 虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分, 但它却有一个别名叫Non-Heap, 目的应该是与Java堆区分开来
  • Oracle的Hotspot虚拟机在Java7中方法区放在'永久代'(Permanent Generation), Java8放在元数据空间, 并且通过GC机制对这个区域进行管理
  • 运行时常量池是方法区的一部分

Java堆

  • Java堆是被所有共享的一块内存区域, 在虚拟机启动时创建
  • 存放对象的实例
  • 垃圾收集器的主要管理区域
  • Java堆还可以细分为: 新生代和老年代, 新生代又可以细分为Eden 空间, From Survivor空间 和To Survivor空间
  • 空间满了会抛OutOfMemoryError

Java虚拟机栈

  • Java虚拟机栈是线程私有的, 它的生命周期与线程相同
  • Java虚拟机栈描述的是Java方法执行的内存模型: 每个方法被执行的的时候都会同时创建一个栈帧(栈帧是方法运行时的基础数据结构)用于存储局部变量表, 操作栈, 动态链接, 方法出口等信息.
  • 栈内存默认最大是1M, 超出则抛出StackOverFlowError

本地方法栈

  • 本地方法栈与虚拟机栈的功能类似, 虚拟机栈是为虚拟机执行Java方法而准备的, 本地方法栈是为虚拟机使用Native本地方法而准备的
  • Hotspot虚拟机中虚拟机栈与本地方法栈的实现方式一样, 超出大小后也会抛StackOverFlowError

程序计数器

  • 程序计数器是线程私有的一块较小的内存空间
  • 记录当前线程执行的字节码位置, 存储的是字节码指令地址, 如果执行Native方法, 则计数器为空
  • CPU同一时间, 只会执行一条线程的指令. JVM多线程会轮流切换并分配CPU的执行时间的方式. 为了线程切换后, 需要通过程序计数器来恢复正确的执行位置

查看class文件内容

使用Demo.Java进行测试, 运行javac Demo.java编译成class文件, 然后运行javap -v Demo.class > Demo.txt查看class文件内容

Demo.Java

public class Demo{
    public static void main(String[] args){
        int x = 500;
        int y = 100;
        int a = x / y;
        int b = 50;
        System.out.println(a + b);
    }
}

Demo.txt

Classfile /E:/*/Demo.class
  Last modified 2019-6-30; size 412 bytes
  MD5 checksum efd785af33e58aa9fc9834110b74b87b
  Compiled from "Demo.java"
public class Demo
  minor version: 0      //次版本号
  major version: 52        //主版本号 版本号规则: JDK5,6,7,8分别对应49,50,51,52
  flags: ACC_PUBLIC, ACC_SUPER        //访问标志
Constant pool:        // 常量池 类信息包含的静态常量, 编译之后就能确认
   #1 = Methodref          #5.#14         // java/lang/Object."<init>":()V
   #2 = Fieldref           #15.#16        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = Methodref          #17.#18        // java/io/PrintStream.println:(I)V
   #4 = Class              #19            // Demo
   #5 = Class              #20            // java/lang/Object
   #6 = Utf8               <init>
   #7 = Utf8               ()V
   #8 = Utf8               Code
   #9 = Utf8               LineNumberTable
  #10 = Utf8               main
  #11 = Utf8               ([Ljava/lang/String;)V
  #12 = Utf8               SourceFile
  #13 = Utf8               Demo.java
  #14 = NameAndType        #6:#7          // "<init>":()V
  #15 = Class              #21            // java/lang/System
  #16 = NameAndType        #22:#23        // out:Ljava/io/PrintStream;
  #17 = Class              #24            // java/io/PrintStream
  #18 = NameAndType        #25:#26        // println:(I)V
  #19 = Utf8               Demo
  #20 = Utf8               java/lang/Object
  #21 = Utf8               java/lang/System
  #22 = Utf8               out
  #23 = Utf8               Ljava/io/PrintStream;
  #24 = Utf8               java/io/PrintStream
  #25 = Utf8               println
  #26 = Utf8               (I)V
{
  public Demo();     // 默认隐式无参的构造函数
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0

  public static void main(java.lang.String[]);        //程序的入口main方法
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC        //访问控制
    Code:
      stack=3, locals=5, args_size=1        //方法栈栈帧中操作数栈的深度,本地变量数量,参数数量
         0: sipush        500        //Jvm执行引擎执行这些源码编译过后的指令码, javap翻译出来的
         3: istore_1                //是操作符, class 文件内存储的是指令码, 前面的数据是偏移量,
         4: bipush        100        //Jvm根据这个去区分不同的指令. 详情参照'JVM指令码表'
         6: istore_2
         7: iload_1
         8: iload_2
         9: idiv
        10: istore_3
        11: bipush        50
        13: istore        4
        15: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        18: iload_3
        19: iload         4
        21: iadd
        22: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
        25: return
      LineNumberTable:
        line 3: 0
        line 4: 4
        line 5: 7
        line 6: 11
        line 7: 15
        line 8: 25
}
SourceFile: "Demo.java"

程序完整运行分析

Java程序运行原理分析 Java程序运行原理分析 Java程序运行原理分析

Java程序运行原理分析

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这