Java程序运行原理分析

class文件内容

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

img

JVM运行时数据区

img

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

线程共享: 所有线程都能访问这块内存数据,随虚拟机或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

1public class Demo{ 2 public static void main(String[] args){ 3 int x = 500; 4 int y = 100; 5 int a = x / y; 6 int b = 50; 7 System.out.println(a + b); 8 } 9}

Demo.txt

1Classfile /E:/*/Demo.class 2 Last modified 2019-6-30; size 412 bytes 3 MD5 checksum efd785af33e58aa9fc9834110b74b87b 4 Compiled from "Demo.java" 5public class Demo 6 minor version: 0 //次版本号 7 major version: 52 //主版本号 版本号规则: JDK5,6,7,8分别对应49,50,51,52 8 flags: ACC_PUBLIC, ACC_SUPER //访问标志 9Constant pool: // 常量池 类信息包含的静态常量, 编译之后就能确认 10 #1 = Methodref #5.#14 // java/lang/Object."<init>":()V 11 #2 = Fieldref #15.#16 // java/lang/System.out:Ljava/io/PrintStream; 12 #3 = Methodref #17.#18 // java/io/PrintStream.println:(I)V 13 #4 = Class #19 // Demo 14 #5 = Class #20 // java/lang/Object 15 #6 = Utf8 <init> 16 #7 = Utf8 ()V 17 #8 = Utf8 Code 18 #9 = Utf8 LineNumberTable 19 #10 = Utf8 main 20 #11 = Utf8 ([Ljava/lang/String;)V 21 #12 = Utf8 SourceFile 22 #13 = Utf8 Demo.java 23 #14 = NameAndType #6:#7 // "<init>":()V 24 #15 = Class #21 // java/lang/System 25 #16 = NameAndType #22:#23 // out:Ljava/io/PrintStream; 26 #17 = Class #24 // java/io/PrintStream 27 #18 = NameAndType #25:#26 // println:(I)V 28 #19 = Utf8 Demo 29 #20 = Utf8 java/lang/Object 30 #21 = Utf8 java/lang/System 31 #22 = Utf8 out 32 #23 = Utf8 Ljava/io/PrintStream; 33 #24 = Utf8 java/io/PrintStream 34 #25 = Utf8 println 35 #26 = Utf8 (I)V 36{ 37 public Demo(); // 默认隐式无参的构造函数 38 descriptor: ()V 39 flags: ACC_PUBLIC 40 Code: 41 stack=1, locals=1, args_size=1 42 0: aload_0 43 1: invokespecial #1 // Method java/lang/Object."<init>":()V 44 4: return 45 LineNumberTable: 46 line 1: 0 47 48 public static void main(java.lang.String[]); //程序的入口main方法 49 descriptor: ([Ljava/lang/String;)V 50 flags: ACC_PUBLIC, ACC_STATIC //访问控制 51 Code: 52 stack=3, locals=5, args_size=1 //方法栈栈帧中操作数栈的深度,本地变量数量,参数数量 53 0: sipush 500 //Jvm执行引擎执行这些源码编译过后的指令码, javap翻译出来的 54 3: istore_1 //是操作符, class 文件内存储的是指令码, 前面的数据是偏移量, 55 4: bipush 100 //Jvm根据这个去区分不同的指令. 详情参照'JVM指令码表' 56 6: istore_2 57 7: iload_1 58 8: iload_2 59 9: idiv 60 10: istore_3 61 11: bipush 50 62 13: istore 4 63 15: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 64 18: iload_3 65 19: iload 4 66 21: iadd 67 22: invokevirtual #3 // Method java/io/PrintStream.println:(I)V 68 25: return 69 LineNumberTable: 70 line 3: 0 71 line 4: 4 72 line 5: 7 73 line 6: 11 74 line 7: 15 75 line 8: 25 76} 77SourceFile: "Demo.java" 78

程序完整运行分析

img img img

CodingDiary

点赞
收藏

评论区

加载中...

相关推荐

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

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

FLV文件格式

1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.