18.JVM

目录

1.编写源代码

2.JDK (Java Development Kit)

3.JRE(Java Runtime Environment)  Java运行时环境

4.JVM

1.类名

2.类文件放在哪?

13JVM按需加载类,那么何时加载一个类?

4.类文件是怎么来的?

5.类文件中的主要数据:

6.为什么要进行类的加载?

7.为什么类文件要按需加载,并且以类为单位加载?

8.类在内存中只会存在一份

9.类的加载过程

10.类的初始化会执行我们的哪些代码,顺序是什么?

11.类的数据被加载到内存的啥位置了?

12.默认类的加载器有哪些:

13.加载时,ClassLoader怎么知道一个类对应的类文件所在的位置?

14.如果加载时一个类不存在,会出现异常

5.类加载时常遇到的问题:双亲(parent)委派机制

6.java中的数据类型:

7.JVM的大体启动过程:控制权如何交到我们手中

8.垃圾回收

1.那么那些是GC的重点?

2.那么如何判断哪些对象是垃圾对象(不会再被使用的对象)

9.如何进行垃圾回收(内存空间的回收)


学习JVM主要是学习java程序运行宁阶段是咋工作的,帮助我们更好地写程序。

1.编写源代码

源码数据一定要存储在某个介质上,并且希望是持久化的存储,所以一般般存在硬盘。

抽象成文件形式(一般以*.java结尾,称为java源文件)

程序 = 数据 +指令

 上述阶段,一般称为开发阶段。(需求分析、编码、编译、测试)

下面进入运行时阶段(Runtime Phase)

CPU无法直接和硬盘(IO设备)做直接的数据交换,我们应该怎么做?


2.JDK (Java Development Kit)

用于给Java开发人员使用的小工具箱

里面放了:

提前准备好的程序(*.exe / *>dll): 编译器、调试工具、运行时的分析工具

官方提供的所有人都可以使用的类文件:*.class

3.JRE(Java Runtime Environment)  Java运行时环境

用于给一般用户运行别人写好的Java程序的一组环境

 这些类不够用,锁把一些官方指定了标准,但按照JDK(JRE)不会安装的类称为JavaEE(Enterprise Edition 企业版)

打包时,只给普通用户使用,只打包*.class就够用了,不用打包EE的 *.class

类文件中的数据:类的基本属性、常量池、方法(方法的信息+指令)

ClassLoader要加载一个类,主要就是加载这些数据到内存中


4.JVM

1.类名

1.权威类名:包名+类名称   mxj.demo.mxj

JVM内部:内部加载器+权威类名,确定一个类是否存在

2.默认情况下:  类加载器(ClassLoader)+权威类名

2.类文件放在哪?

硬盘中,以文件的形式出现最为常见

13JVM按需加载类,那么何时加载一个类?

实例化对象、访问静态属性、调用静态方法、子类用到父类

什么叫用到?

使用一个类,进行对象的实例化(构造对象时)

使用一个类时,会触发这个类的父类(“父类”:类的继承、接口的实现、接口的继承)

4.类文件是怎么来的?

经过编译器,将java源文件编译出来

5.类文件中的主要数据:

基本信息(静态属性)、方法(方法信息、指令(字节码))、常量

6.为什么要进行类的加载?

按照冯诺依曼体系,CPU无法直接读取硬盘的数据,需要先加载到内存中

7.为什么类文件要按需加载,并且以类为单位加载?

相对来说,节省内存空间,实现方便

8.类在内存中只会存在一份

9.类的加载过程

加载loading、链接Linking、初始化Initializing

10.类的初始化会执行我们的哪些代码,顺序是什么?

(1)属性的初始化赋值

(2)静态构造代码块

父类的初始化一定在子类之前完成

按照书写顺序

11.类的数据被加载到内存的啥位置了?

逻辑上,房子啊方法区。但不同的JVM实现,可以有进一步讨论空间

12.默认类的加载器有哪些:

不同的类,由不同的类加载

Boostrap ClassLoader(启动类加载器):加载SE下的标准类(java.lang.String、java.util.List、

java.io.InputStream)

Extenttion ClassLoader(扩展类加载器):加载SE下的扩展类(我们一般用不上)

Application ClassLoader(应用类加载器):我们写的类、我们通过maven或者其他工具引入的第三方类

13.加载时,ClassLoader怎么知道一个类对应的类文件所在的位置?

启动、扩展类加载器根据固定位置找。

应用类加载器,根据class path的路径依次查找

14.如果加载时一个类不存在,会出现异常

(ClassNotFound、NoClassF...)


5.类加载时常遇到的问题:双亲(parent)委派机制

默认的三个类加载器之间遵守的一个规范:

1.三个类加载器之间存在

2.ApplicationClassLoader需要类加载的时候,先委派给双亲去加载

如果parent加载成功这个类了,就不用再加载了,否则就自己去加载

3.目的是防止加载进来用户写好的恶意代码

前提知识点:一个类(A)用到其他类(BCD),则其他的这些类(BCD)的加载动作,默认是由当时加载A类的加载器来加载

面试重点:

假设有一个com.mxj.demo.Main用到了java.lang.String类还是java.lang.String?

         

 com.mxj.demo.Main类被哪个类加载器加载?  ApplicationClassLoader去加载

Main用到了java.lang.String  ,默认让  ApplicationClassLoader去加载

如果有双亲委派,ApplicationClassLoader优先让BootStrapClassLoader去加载rt.jar下的。所以,不会加载我们自己写的。


6.java中的数据类型:

1.基本数据类型(Primitive Type):空间保存的是值,访问内存是一次性的

2.引用数据类型(Reference Type):空间中保存的真实对象的线索(地址、其他信息)

                                                         访问内存至少两次

一、Java中的基本类型:

1.数值类型

       (1)整形 byte、char、int、long、

       (2)非整形  float、double

2.布尔类型

二、Java中的引用类型:

类、接口、数组、注解


执行引擎:就是对CPU的模拟,所以CPU的工作与执行引擎相同

1.读取PC中保存的值(一般是地址)

2.根据PC的值,去内存中(方法区),读取一条指令(字节码)

3.执行具体的字节码

4.默认情况下,PC的值自动加一(语句自动执行下一条)


7.JVM的大体启动过程:控制权如何交到我们手中

我们main方法的第一条语句(字节码)是如何被执行起来的

java.exe -classpath指定类的加载路径   启动类名称

java.exe  com.mxj.demo.Main   以这个类的main方法作为程序的启动入口

1.[OS]收集要启动进程的信息,程序是C:/Program Files/Java/jdk/bin/java.exe,参数是com.mxj.demo.Main

2.[OS]根据程序,启动进程,执行java.exe当时写的程序入口(C语言里的main函数)

3.[JVM]读取参数,找OS申请必要的内存(malloc)、创建必要的执行应用类和类加载器

4.[JVM]执行引擎,要求类加载器进行com.mxj.demo.Main类的加载

5.[JVM]创建主线程,把PC的值设成com.mxj.demo.Main类下的static main的第一条指令的地址

6.[JVM]开启执行引擎的指令执行循环,执行第一条语句

7.[Java App]开始我们代码的执行

8. .....直到所有前台线程

9.[JVM]进行必要资源的回收

10.[JVM]进程退出


8.垃圾回收

有了GC(垃圾回收)之后,让开发人员只需要考虑什么时候需要一块内存,而不需要考虑什么内存不再被需要了。

逻辑上,把内存的使用权和所有权分离了,我们只享受一段内存的使用权,没有所有权。

好处:不需要考虑内存的释放问题

坏处:内存彻底和我们无缘

1.那么那些是GC的重点?

1.PC区域:一个PC和一个线程关联,只要线程活着,PC就一定需要

分配时机:创建一个新线程

回收时机:这个PC对应线程的最后一条指令执行结束之后

分配和回收的时机非常简单,不需要GC做过多的参与

2.栈区域:每个线程都有自己的栈,创建线程时为其分配栈空间。线程执行结束后回收栈空间

栈上栈帧的分配:当执行一个方法的调用时

回收栈帧:当该方法return时

分配和回收的时机非常简单,不需要GC做过多的参与

3.方法区(包含运行常量池)

分配:类的加载

回收:类的卸载

不需要GC做过多的参与

4.堆区(以对象为基本单位)

分配:实例化一个对象     时机非常明确:new 语句出现的时候

回收:该对象一定没有在被使用的时候

一个对象没有被使用,但是还没被回收。        可以接受,一部分内存被浪费了。

一个对象还在使用,但被回收了。                   不可接受,造成野指针(访问了错误的空间)


2.那么如何判断哪些对象是垃圾对象(不会再被使用的对象)

1.引用指针法

 object.ref_count 何时增加,何时减少,关键就看引用的生命周期。

增加:每多一个引用指向该对象(进行了引用赋值),就要增加

减少:引用出现的位置

(1)栈帧中(局部变量),方法执行结束,引用声明周期消亡,ref_count--;

(2)出现在类中(静态属性),类被卸载时,引用生命周期消亡

(3)对象的死亡引起的连锁反应

          对象死亡,对象中的引用失效,导致该引用指向的对象的ref_Count--,可能引起其他对象继续死亡。

(4)引用还在,但指向其他对象了

9.如何进行垃圾回收(内存空间的回收)

对象的生命:每经历一次GC,对象的年龄+1

大部分情况下,只会进行新生带的GC。随着新生代GC的进行,会有越来越多的对象进入老年代。

由于老年代的GC成本较大,所以一般会尽量减少老年代GC

随着老年代GC对象越来越多,达到某个阈值,就会进行老年代GC

大部分情况下,老年代GC总是由于某次新生代GC引起的。所以,新生带GC发生时,一般也代表了整个GC。

如果对象本身很大,复制起来成本很高,一般直接进入老年代。

为啥15岁成年:

Hostpot内部实现对象时,用了4个bit来记录年龄,年龄就是0-15

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值