java堆栈
- Java程序运行流程
- Java程序运行原理分析----环境介绍
从最初的jdk安装开始,都是程序运行的关键步骤,每一个步骤都正确执行,一台电脑上才真正的能够运行Java程序。
工欲善其事,必先利其器。这里作为一个Java开发人员,平时跟代码打交道,但是这里,所谓的代码,其实是源代码,供程序开发人员间相互阅读使用的。
而在开发源代码之前,每一个开发人员都需要使用工具才能完成开发任务(jdk本身是一个工具集,不同版本的jdk. 就好像是 人类沟通交流的演变一样,最初原始社会,没有语言,人类为了方便交流沟通,逐渐产生各种语言,作为一个中国人就拿中文举例吧,当代环境下比较流行的是简体中文,繁体中文,而简体中文是繁体中文的简化版,这就意味着,如果时间回溯到前100年左右的时间,那当时应该广泛使用的是繁体中文,学校里面教授的课程也都是基于繁体中文而产生的。对于编程语言来说,也是同样的道理,jdk的版本也是随时代发展而演变的,虽然都支撑了同样功能的实现,但是实现的方式可能会有些差异,而最终实现出来的结果却是相同的)
-
- JDK,JRE 与JVM的区别
JVM :英文名称(Java virtual Machine),就是我们耳熟能详的 Java 虚拟机。它只认识 xxx.class 这种类型的文件,它能够将 class 文件中的字节码指令进行识别并调用操作系统向上的 API 完成动作。所以说,jvm 是 Java 能够跨平台的核心
JRE :英文名称(java runtime environment),我们叫它:Java 运行时环境。它主要包含两个部分,jvm 的标准实现和 Java 的一些基本类库。它相对于 jvm 来说,多出来的是一部分的 Java 类库。
JDK :英文名称(Java Development Kit),Java 开发工具包。jdk 是整个 Java 开发的核心,它集成了 jre 和一些好用的小工具。例如:javac.exe,java.exe,jar.exe 等。
关系描述:
-
- Java程序运行
本质上是JVM读取字节码文件(.class文件) 通过安装的JRE和底层系统之间的API
实现的Java程序运行的,也是java代码一处编写到处运行的本质。
我是如何总结出上面的图片的:
- 对jdk程序包的梳理(安装方式的选择会照成以下两种情况)
Jdk1.6包里面的内容,有jdk 和 jre两部
jdk1.8包里面只有jdk
造成这种情况的原因就是安装的时候勾选的选项不同,具体是哪选项影响的这里就不介绍了
其实如果作为一个Java的开发人员,只安装jdk就够了(这里其实会包含一个jre的环境),而系统运行只安装jre就够,两者的存在没有必然的关系,更深层的目录结构就不一一介绍了,可以自己点进去看看,思考思考
- 还有就是历史知识的沉淀和积累,当知识沉淀到一定数量的时候,一定要把这
些知识间的关系打通,要不然永远都是停留在同一个地方,没有进步
这里要思考一个问题如下:
-
- JVM运行时数据区
前面描述了这么多,其实都是为了今天主角出场,做的一些基础铺垫,以便我们
之间不存在沟通交流的障碍,俗称代沟。
先传两张方便理解的图,然后对图内容进行具体描述:
线程独占部分:每个线程都会有它独立的部分,随线程声明周期而创建和销毁
线程共享部分:所有线程都能访问这块内存数据,随虚拟机或GC而创建和销毁
方法区:JVM用来存储加载的类信息、常量、静态变量、编译后的代码数据
虚拟机规范中方法区是一个逻辑区划。具体实现根据不同虚拟机来实现的。
如:oracle的HotSpot在java7中方法区放在永久代,java8放在元数据空间,并且通过GC机制对这个区域进行管理(JVM不是用JAVA编写的,但是可以用面向对象的思维来思考,如果使用JAVA来处理这个运行时数据区的问题,会编写成什么样子的代码,上图中列出使用面向对象的封装+伪代码 的实现)
堆内存:还可以细分为老年代,新生代(新生代中又有Eden,From Survivor , To Survivor)
JVM启动时创建,存放对象的实例。垃圾回收器主要是管理堆内存的。如果满了,就会出现outofmemoryERROR(这里依旧使用对象思维 就是JVMRuntimeData 中有一个 heapArea 而这个heapArea是一个自定义类型的对象(会有oldObject , newObject),newObject(新生代) 又是一个新的自定义类型变量(会有 Eden,From Survivor, To Survivor这些属性) , 而GC就可以封装成一个方法,如果方法区和堆内存所占用的空间总和大于JVM申请到的内存空间就抛出异常,当然还会有其他各种各样的情况,对应着各种各样的异常 )
虚拟机栈,每个线程都在这个空间有一个私有的空间。
线程栈由多个栈帧(stack Frame) 组成。
一个线程会执行一个或多个方法,一个方法会对应一个栈帧
栈帧内容包含:局部变量表,操作数栈,动态链接,方法返回地址,附加信息等。
栈内存默认最大是1M,超出则抛出stackoverflowerror
这里可以试着用面向对象的思维,将栈帧封装成一个对象理解一下
本地方法栈:和虚拟机栈功能类似,虚拟机栈是为虚拟机执行Java方法而准备的,本地方方法是为虚拟机使用native本地方法而准备的。
虚拟机规范没有规定具体的实现,由不同的虚拟机厂商去实现。
HotSpot虚拟机中虚拟机栈和本地方法栈的实现是一样的。同样,超出大小后会抛出StackOverflowError ( 这里其实就是调用操作系统API 的一个过程 )
程序计数器(Program Counter Register) 记录当前线程执行 字节码的位置,存储的是字节码指令地址,如果执行 native方法,则计数器值为空
每个线程都在这个空间有一个私有的空间,占用内存空间很少。
cpu同一时间,只会执行一条线程中的指令。JVM多线程会轮流切换并分配CPU执行时间的方式。 为了线程切换后,下一次CPU 继续执行该线程的时候准确的找到执行位置,所以需要通过程序计数器,来恢复正确的执行位置。(指的是字节码的指令位置)
(这里程序计数器是JVM记录java的 .class文件执行位置而存在的, native并非java 的.class文件,是没有办法记录到的, native 方法是指底层操作系统提供API 或者通过其他语言编写的底层代码)
- 实操演示
编写测试类:
public class Demo1{
public static void main(String[] args){
int x = 500;
int y = 100;
int a = x/y;
int b = 50;
System.out.pritln(a+b);
}
}
javac Demo1.java
javap -v Demo1.class > Demo1.txt
经过一系列操作会出现上述的文件结构
打开Demo1.txt会出现如下的class文件内容
minor version //次版本号
major version //主版本号
flags //访问标志
主版本号规则:jdk5,6,7,8分别对应49,50,51,52
访问标志表如下
.class文件部分 详细参考资料:
https://www.jianshu.com/p/9c3f057e382b
Java 中文指引连接地址
https://www.oracle.com/technetwork/cn/java/javase/documentation/index.html
文章最后发布于: 2019-05-21 02:54:29
相关阅读
总结一下我使用过的4种类型的定时器:@Scheduled注解、quartz、new Timer().schedule、使用线程控制。 1.@Scheduled注解 @Schedul
dk安装与配置jdk for windows1、下载官网地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html局域网下载:ft
如何提升创意,又如何才能获得源源不断的创意?笔者针对这个问题,总结了大脑的三个功能引发创新的原理,enjoy~广告人:这个广告创意,我为什
作为网站管理员,无论是个人站,还是企业站,甚至是门户站,最担心的无非就是不被搜索引擎所收录,在引擎里面得不到关键词相应的排名;然后,
在C语言中,ANSIC C程序库提供rand()函数来产生随机数。但事实上,rand()是并不是一个真正的随机数产生器,即可以预测随机序列的顺序,在