关于:Java与jvm关系,和本人对java虚拟机中运行时数据区的一丢丢理解

jvm与java

jvm与Java其实没有必要的联系,那作为一个学习java的人为什么要去了解jvm呢?
其实我的理解是,也是我们这种小白需要知道的就只是jvm能够帮助Java实现跨平台的功能。而java这么火热的很重要的原因之一就是他的跨平台性。

那使用jvm的时候需不需要单独下载呢?

首先,你们学习java的第一步就是需要下载并配置jdk环境,而一般下载的jdk里面就有jre,jvm就在jre里面,所以对于初学者来说你是不用再次下载jvm的,如下
在这里插入图片描述

那jvm是怎么帮助Java实现跨平台的呢?

在配置好环境以后,就到写java程序的时候了,创建并运行一个java程序的一般步骤为
1.创建并编写.java文件。
2.编译这个.java文件,可以在控制台输入javac命令编译,编译成功会生成一个.class文件,俗称字节码文件。
3.运行这个生成的.class字节码文件。
经历着三步以后才算得上成功编写并运行一个Java程序了,而jvm就是负责将你第二步生成得字节码文件翻译成特定平台下的机器码运行,特定平台的意思是jvm有很多不同平台的版本,之所以能跨平台就是因为它可以在你其他文件不变的情况下,只需要在不同平台下下载相对于的jvm,就可以轻松实现跨平台了。

运行时数据区

先放图镇楼,这是我画的:在这里插入图片描述
这里面有一个最外层的大框表示运行时数据区,里面有很多小框,左边绿色(表示线程共享),右边橙色(表示线程私有)。

一:线程私有的(虚拟机栈,本地方法栈,程序计数器)
1:程序计数器

程序计数器又可以看成行号指示器,他的作用是用来存储指向下一条指令的地址,也就是即将要执行的代码,由执行引擎来读取下一条指令。
因为他只存储了地址信息,所有他只占用很小的内存,而且运行速度是最快的,并且还不用考虑GC(垃圾回收),与OOM(溢出问题)这两个问题。
程序计数器时线程私有的,因为Java虚拟机是并发运行的,并发的意思就是说多个线程不停的交换运行,比如:一会儿是线程1在运行,一会儿是线程2运行,一会儿又返回线程1运行。
如果线程共享的话:那么在线程交换运行的过程中就会产生一系列问题,比如线程1运行到第3行代码时需要转到线程2运行,那么线程2运行到第5行以后又跳转回到线程1执行,那么线程1就不会从第3行开始执行了,他就会从第5行开始运行,因为程序计数器时共享的。

2:Java虚拟机栈

主要管理java程序运行的地方,线程私有,生命周期与线程相同,运行速度仅次于程序计数器,不存在GC(垃圾回收)问题,但是存在OOM(溢出)问题,
每个方法执行的时候都会同步生成一个栈帧用于存储局部变量表、操作数栈、动态连接、方法出口等信息。
其中局部变量中存放了,八种基本数据类型(byte,short,char,int,long,float,double,boolean)
和引用类型变量的引用地址

3:本地方法栈

本地方法栈是为虚拟机使用到的本地方法服务,和虚拟机栈类似,不过就是虚拟机栈为虚拟机执行Java方法(也就是字节码) 服务而已

二:线程共享(方法区,Java堆)
1:java堆

是虚拟机所管理的内存总最大的一块,在虚拟机启动时创建,在被创建的时候大小就固定了,此内存区域唯一的目的就是用来存放对象实例的,几乎所有对象都在这里分配。
而且Java堆是垃圾回收管理的内存区域。从回收内存的角度看,由于现代垃圾收集器大部分都是基于分代收集理论设计的,所以Java堆中经常会出现“新生代”“老年代”“永久代”等。
如果从分配内存的角度看, 所有线程共享的Java堆中可以划分出多个线程私有的分配缓冲区 ,以提升对象分配时的效率。不过无论从什么角度,无论如何划分,都不会改变Java堆中存储内容的共性,无论是哪个区域,存储的都只能是对象的实例,将Java堆细分的目的只是为了更好地回收内存,或者更快地分配内存。

2:方法区

方法区用于存储已被虚拟机加载的类信息、 常量、 静态变量、 即时编译器编译后的代码缓存等数据,而且为了与java堆区分开来还有一个別名“非堆”。
在jdk8以前很多程序员都原因叫方法区为“永久代”,因为他们都习惯在HotSpot虚拟机上开发、 部署程序。不过在jdk8以后,随着永久代的取消,元空间的出现,这个说法也就没有了。而且为了考虑到HotSpot的未来,采用本地内存来实现方法区是特别不容易产生OOM异常的,因为本地内存一般都是很大的。

猜你喜欢

转载自blog.csdn.net/qq_49249150/article/details/107305323
今日推荐