Java程序运行原理分析

北战南征 提交于 2019-12-30 23:33:18

1. JVM 简介

在这里插入图片描述
java源码被编译器成class字节码,然后由JVM运行的时候进行处理,下面一部分主要是JVM根据不同的操作系统进行的适配。

线程独占:每个线程都会有它独立占据的空间,随线程生命周期而创建和销毁
线程贡献:所有线程都能访问这块内存数据,随虚拟机或者GC创建和销毁

方法区:用来存储加载的类的信息、常量、静态变量、编译后的代码等东西的。方法区在1.7以前把它叫做永久代,1.8之后叫做元数据空间。
在这里插入图片描述

虚拟机栈:主要就是存储栈帧的,一个线程的执行会有一个或多个方法被执行,这个时候一个栈帧就对应一个方法。栈帧的内容包括:

  • 局部变量表
  • 操作数栈
  • 动态链接
  • 方法返回地址
  • 附加信息等

栈内存默认大小为1M,如果超出会报StackOverflowError;(就像你写一个无限递归的方法,肯定会报这个错)

本地方法栈:和虚拟机栈差不多,但是放的是本地方法(native修饰的),超出大小也会报StackOverflowError

程序计数器:记录当前线程执行字节码的位置,存储的是字节码指令地址,如果执行Native方法,则计数器值为空。它在每个线程的私有空间中占有一部分空间,只是很小的一部分。它是因为CPU在同一时间只会执行一个线程,所以需要记录下当前执行的位置,使得激活的时候可以无缝衔接。

2. Class文件简介

class文件是一串二进制流,中间无任何分隔符;文件开头是一个0xcafebabe的特殊标志,象征了咖啡宝贝(与Java图标相对应),主要有版本、访问标志、常量池、当前类、超级类(父类)、接口、字段、方法、属性等内容。

在这里插入图片描述

3. 查看java源码的.class文件内容

以下是一个java源码文件的内容:

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

先编译成.class文件:

javac Demo1.java

生成可查看的文本并保存到Demo1.txt中:

javap -v Demo1.class > Demo1.txt

打开Demo1.txt文件,内容如下:

Classfile /E:/wangyiyun/wangyiyun/src/Demo1.class
  Last modified 2019-12-30; size 414 bytes
  MD5 checksum ae6fa820973681b35609c75631cb255b
  Compiled from "Demo1.java"
public class Demo1
  minor version: 0	//次版本号
  major version: 52		//主版本号 49对应5 50对应6 51->7 52->8
  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            // Demo1
   #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               Demo1.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               Demo1
  #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 Demo1();
    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[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=5, args_size=1
         0: sipush        500
         3: istore_1
         4: bipush        100
         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: "Demo1.java"


解析:

  • 基本信息
  minor version: 0	//次版本号
  major version: 52		//主版本号 49对应5 50对应6 51->7 52->8
  flags: ACC_PUBLIC, ACC_SUPER //访问标志

在这里插入图片描述

  • Constant pool
    常量池对应的是类编译之后的静态信息,编译之后就能确认。
  • 构造函数
 public Demo1();
    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

由此可见,java会为每个类生成一个默认的无参构造函数

  • main方法
    在这里插入图片描述
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!