【主题】
JAVA程序运行原理分析
【信息】
class文件内容
字节码,开头包含一个0xcafebabe(16进制)特殊的一个标志
魔数cafebabe来源可参考WIKI百科: Java_class_file
class文件可用二进制软件查看,比如ultraedit,我用notepad++的ansi转hex看不出来开头的魔数,应该是原来class文件是windows1252编码问题。
JVM运行时数据区
线程共享(所有线程能访问这块内存数据,随虚拟机或者GC而创建和销毁)部分:
- 方法区:存放class的一些信息,类信息、常量、静态变量、编译后的代码等数据
- 堆内存:对象实例的存放,垃圾回收主要管理。细分为:老年代、新生代(Eden、From Survivor、To Survivor)。如果满了oom。
最近看到一篇文章-Linux与JVM的内存关系分析,分析内存泄漏问题,应该能更好地理解堆内存吧。
线程独占(每个线程都会有它独立的空间,随线程生命周期而创建和销毁)部分:
- 虚拟机栈
- 本地方法栈
- 程序计数器
不用深入了解底层,有兴趣自行去了解。
底层:执行引擎->本地库接口->本地方法库
虚拟机栈
概念:每个线程都在这个空间有一个私有的空间
- 线程栈由多个栈帧(Stack Frame)组成
- 一个线程会执行一个以上方法,一个方法对应一个栈帧
- 栈帧包含:局部变量表、操作数栈、动态链接、方法返回地址、附加信息等。
- 栈内存默认最大是1M,超出则抛出StackOverflowError
本地方法栈
和虚拟机栈类似,只是执行的方法不同。虚拟机栈是为虚拟机执行JAVA方法而准备的,本地方法栈是为虚拟机使用Native本地方法而准备的。
虚拟机规范没有规定具体的实现
程序计数器(Program Counter Register)
记录当前线程执行字节码的位置,存储的是字节码指令地址,如果执行Native方法,则计数器为空。
查看class文件内容
javap -v Demo1.class>Demo1.txt
输出所有的class信息到Demo1.txt
class内容-版本号/访问控制
major version: 52
,版本号规则:JDK5,6,7,8分别对应49,50,51,52
访问标志表要记住
class内容-常量池
跟字符串常量池不一样,这个是编译之后类里面包含的一些静态常量,比如方法名称
class内容-构造方法
没有定义构造函数时,会有隐式的无参构造函数
class内容-程序入口main方法
stack=3, locals=4, args_size=1
本地变量数量,参数数量,方法对应栈帧中操作数栈的深度。
javap翻译出来的是操作符,class文件内存储的是指令码。
程序完整运行分析(一)
加载信息到方法区,运行时常量池:字符串常量
HotSpot虚拟机:
- 1.7和之前称为永久代
- 1.8开始称为元数据空间
程序完整运行分析(二)
JVM创建线程来执行代码,在虚拟机栈、程序计数器内存区域中创建线程独占的空间。
- 虚拟机栈:Thread(栈帧)
- 程序计数器:Thread执行位置-字节码指令地址
程序完整运行分析(三)
虚拟机栈:
main方法栈帧:
- 本地变量表:赋值给变量
- 操作数栈:入栈和出栈
程序计数器:当前线程执行位置
所谓的指令码执行,它就是对栈帧里面的本地变量表、操作数栈以及栈帧的一些信息进行不断的操作,以及多个栈帧交替执行,达到了程序运行的最终效果
结语
JVM运行原理中更底层实现,针对不同的操作系统或者处理器,会有不同的实现-这也是Java能够实现“一处编写,处处运行”的原理
【思考】
详细讲解了JVM运行java代码的原理,知其然还要知其所以然。
- 但是了解这些有什么用呢?
【行动/反馈】
去百度查下思考的问题?
- 性能优化:懂原理, 才能真正的对代码进行优化, 提升程序的性能和效率
【钩子】
java运行原理 jvm运行分析 class文件分析