当我们真正运行程序的时候,CPU是读不懂这些英文的,所以我们需要先转化成可执行的二进制文件,这个过程通常由编译器完成。有些编译器直接将源代码编译成机器码,载入内存后CPU可以直接运行。而机器码的格式是跟具体的CPU架构相关的,Intel的CPU机器码对于ARM CPU来说是无法理解的。因此,同样的源代码需要根据不同的硬件进行特定的编译。好了,高级语言到低级语言的桥梁就是编译器。我们写好源代码,编译器将源码编译成可执行的机器码,然后CPU读取机器码,执行程序。
Java源代码(.java)经过java编译器(javac.exe)编译之后,并没有直接转化为机器码,而是转化成一种中间格式,成为字节码(.class),字节码再经过java虚拟机转化成特定CPU架构的机器码。也正是因为这一中间物,java才有所谓的跨平台。
.java 源代码编译==>.class ==>JVM
线程独占:每个线程都有它独立的空间,随线程生命周期而创建和销毁
线程共享:所有线程都能访问这块内存区域,随虚拟机或者GC而创建和销毁
方法区:JVM用来存储加载的类信息、常量池、静态变量、编译后的代码等数据,虚拟机规范中这是一个逻辑区,具体实现根据步同虚拟机来实现,如:Oracle的HotSpot在java7中方法区放在永久代,java8放在元数据空间,并且通过GC机制对这个区域进行管理。
堆内存:还可以细分为、新生代、老年代(Eden、From Survivor、To Survivor)JVM启动是创建,存放对象的实例。垃圾回收器主要就是管理堆内存。如果满了,就会出现OutOfMemroryError。
虚拟机栈:每个线程都在这个空间有一个私有的空间。线程栈由多个栈帧(Stack Frame)组成。一个线程栈会执行一个或多个方法,一个方法对应一个栈帧。栈帧内容包含:局部变量、操作数、动态链接、方法返回地址、附加信息等。栈内存默认最大是1M,超出则抛出StackOverflowError。
本地方法栈:和虚拟机栈功能类似,虚拟机是为虚拟机执行JAVA方法而准备的,本地方法栈是为虚拟机适用Native本地方法而准备的。虚拟机规范没有规定具体的实现,由不透的虚拟机厂商去实现。HotSpot虚拟机中虚拟机栈和本地方法栈的实现一样的。同样超出大小以后也会抛出StackOverflowError。
程序计数器:(Program Counter Register)记录当前线程执行字节码的位置,存储的是字节码指令地址,如果执行Native方法,则计数器值为空。每个线程都在这个空间由一个私有的空间,占用内存空间很少。CPU同一时间,只会执行一条线程中的指令。JVM多线程会轮流切换并分配CPU执行时间的方式,为了线程切换后,需要通过程序计数器,来恢复正确的执行位置。
编译下面java文件 javac,编译成class文件,利用javap命令的解析结果说明,查看Demo1.txt;
//编译
javac Demo1.java
//javap查看内容
javap -v Demo1.class>Demo1.txt
public class Demo1 {
public int x;
public int sum(int a, int b) {
return a + b;
}
public static void main(String[] args) {
Demo1 demo1 = new Demo1();
demo1.x = 3;
int y = 2;
int z = demo1.sum(demo1.x, y);
System.out.println("person age is " + z);
}
}
class内容
Classfile /D:/Demo1.class
Last modified 2018-12-31; size 795 bytes
MD5 checksum e4a628b971c32236aec9fb9b2672408d
Compiled from "Demo1.java"
public class com.study.hc.thread.chapter1.thread.Demo1
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #14.#27 // java/lang/Object."<init>":()V
#2 = Class #28 // com/study/hc/thread/chapter1/thread/Demo1
#3 = Methodref #2.#27 // com/study/hc/thread/chapter1/thread/Demo1."<init>":()V
#4 = Fieldref #2.#29 // com/study/hc/thread/chapter1/thread/Demo1.x:I
#5 = Methodref #2.#30 // com/study/hc/thread/chapter1/thread/Demo1.sum:(II)I
#6 = Fieldref #31.#32 // java/lang/System.out:Ljava/io/PrintStream;
#7 = Class #33 // java/lang/StringBuilder
#8 = Methodref #7.#27 // java/lang/StringBuilder."<init>":()V
#9 = String #34 // person age is
#10 = Methodref #7.#35 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#11 = Methodref #7.#36 // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
#12 = Methodref #7.#37 // java/lang/StringBuilder.toString:()Ljava/lang/String;
#13 = Methodref #38.#39 // java/io/PrintStream.println:(Ljava/lang/String;)V
#14 = Class #40 // java/lang/Object
#15 = Utf8 x
#16 = Utf8 I
#17 = Utf8 <init>
#18 = Utf8 ()V
#19 = Utf8 Code
#20 = Utf8 LineNumberTable
#21 = Utf8 sum
#22 = Utf8 (II)I
#23 = Utf8 main
#24 = Utf8 ([Ljava/lang/String;)V
#25 = Utf8 SourceFile
#26 = Utf8 Demo1.java
#27 = NameAndType #17:#18 // "<init>":()V
#28 = Utf8 com/study/hc/thread/chapter1/thread/Demo1
#29 = NameAndType #15:#16 // x:I
#30 = NameAndType #21:#22 // sum:(II)I
#31 = Class #41 // java/lang/System
#32 = NameAndType #42:#43 // out:Ljava/io/PrintStream;
#33 = Utf8 java/lang/StringBuilder
#34 = Utf8 person age is
#35 = NameAndType #44:#45 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#36 = NameAndType #44:#46 // append:(I)Ljava/lang/StringBuilder;
#37 = NameAndType #47:#48 // toString:()Ljava/lang/String;
#38 = Class #49 // java/io/PrintStream
#39 = NameAndType #50:#51 // println:(Ljava/lang/String;)V
#40 = Utf8 java/lang/Object
#41 = Utf8 java/lang/System
#42 = Utf8 out
#43 = Utf8 Ljava/io/PrintStream;
#44 = Utf8 append
#45 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder;
#46 = Utf8 (I)Ljava/lang/StringBuilder;
#47 = Utf8 toString
#48 = Utf8 ()Ljava/lang/String;
#49 = Utf8 java/io/PrintStream
#50 = Utf8 println
#51 = Utf8 (Ljava/lang/String;)V
{
public int x;
descriptor: I
flags: ACC_PUBLIC
public com.study.hc.thread.chapter1.thread.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 6: 0
public int sum(int, int);
descriptor: (II)I
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=3
0: iload_1
1: iload_2
2: iadd
3: ireturn
LineNumberTable:
line 10: 0
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=4, args_size=1
0: new #2 // class com/study/hc/thread/chapter1/thread/Demo1
3: dup
4: invokespecial #3 // Method "<init>":()V
7: astore_1
8: aload_1
9: iconst_3
10: putfield #4 // Field x:I
13: iconst_2
14: istore_2
15: aload_1
16: aload_1
17: getfield #4 // Field x:I
20: iload_2
21: invokevirtual #5 // Method sum:(II)I
24: istore_3
25: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
28: new #7 // class java/lang/StringBuilder
31: dup
32: invokespecial #8 // Method java/lang/StringBuilder."<init>":()V
35: ldc #9 // String person age is
37: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
40: iload_3
41: invokevirtual #11 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
44: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
47: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
50: return
LineNumberTable:
line 14: 0
line 15: 8
line 16: 13
line 17: 15
line 18: 25
line 19: 50
}
SourceFile: "Demo1.java"
程序运行