面试内容-java部分基础

1.java平台无关性
在这里插入图片描述
为什么JVM不直接将源码解析成字节码去执行:(ByteCode是JVM唯一能够识别的指令,JVM将ByteCode翻译成真正能够执行的机器码)
准备工作:每次执行都需要各种检查(过于复杂)
兼容性:也可以将别的语言解析成字节码去执行。

2.jVM如何加载.class文件
Java虚拟机:抽象化的计算机。
存在的原因:屏蔽底层操作系统的不同,并且减少基于原生语言开发的复杂性。
JVM是内存虚拟机。JVM有完善的硬件架构。如处理器,堆栈,寄存器,相应的指令系统等
JVM的架构如下:
在这里插入图片描述
3.java反射机制
Java反射机制是在运行状态中。对于任意一个类,都能够知道这个类的所有属性跟方法;对于任意一个对象,都能够调用它的任意方法跟属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。

4.谈一谈ClassLoader
类从编译到执行的过程:
在这里插入图片描述
在这里插入图片描述
ClassLoader:
BootstarpLoader:C++编写,用于加载核心类库java.*
ExtClassLoader: java编写,加载扩展库javax.*用户可见
从本地路径下查询相关的文件,有的话就进行加载。并且不是一次性加载,是用到才会加载。 相关代码如下:
在这里插入图片描述
AppClassLoader: java编写,用于加载程序所在目录。用户可见。
用来加载classpath下面的内容的。
去路径下找我们刚刚编译好的class
在这里插入图片描述
用户自定义的ClassLoader: java编写,定制化加载
自定义ClassLoader的实现:
关键函数:
在这里插入图片描述
5.ClassLoader的双亲委派机制
在这里插入图片描述
自底向上检查类对应的ClassLoader是否已经加载。完成此步骤的代码如下:
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
自顶向下尝试加载类,在对应的目录下查找是否有对应的jar包(类比:Robot.class)代码如下:
c = findClass(name);
使用双亲机制的核心目的:避免多份同样的字节码的加载

6.类的装载过程
在这里插入图片描述
链接的过程:
校验:举例:检查class的格式是否准确
准备:为类变量分配存储空间并设置变量初始值,类变量随类型信息存放在方法池中。生命周期很长,使用不当很容易造成内存泄漏。类变量就是static变量,初始值指的是类变量的默认值,而不是实际要赋的值。

LoadClass和forname的区别:
同:都能在运行时候,对任意一个类,都能够知道该类的所有属性跟方法。对于任意一个类,都能够调用他的方法跟属性。比较它们之前,需要了解Java类装载的过程。
作用:
异:class.forname()得到的class是已经初始化。(初始化就代表已经完成第三步了)
Classloder.loadClass得到的class是还没有链接的。
例:数据库驱动的加载,需要使用Class.forname().因为需要执行代码块中的静态部分。进而生成Driver对象。
例:数据库驱动的加载,需要使用Class.forname().因为需要执行代码块中的静态部分。进而生成Driver对象。
在这里插入图片描述

Classloder.loadClass的实际应用场景:在SpringIOC中,资源加载器在获取要读入的资源的时候,即读取一些bean的配置信息的时候,如果是以classpath的方式加载,就要使用Classloder.loadClass来加载,这样做是因为SpringIOC的懒加载机制有关。SpringIOC为了加快加载速度,大量使用lazyLoading。

7.JVM内存模型:线程私有
就是JVM架构中的RuntimeDataArea。
线程角度:
在这里插入图片描述
程序计数器:
当前线程所执行的字节码的行号指示器(逻辑)
改变计数器的值来选取下一条需要执行的字节码
和线程是一对一的关系即线程私有
对于Java方法计数,如果是native方法,则计数器的值为undefined
不会发生内存泄露

Java虚拟机栈:栈是后进先出。
在这里插入图片描述
在这里插入图片描述
局部变量表为操作数栈提供数据支撑。
在这里插入图片描述
Iconst_0:表示将int数0压入操作数栈当中。
Istore_2:将操作数栈栈顶元素0pop出来,存储到局部变量表的第2个变量当中(从零开始计算)。Store=出栈。
Iload_0:表示将局部变量表的第0个变量压入操作数栈栈顶。Load=入栈。
Iload_1:表示将局部变量表第1个变量压入操作数栈栈顶。
Iadd:将操作数栈里的1和2弹出,通过2+1去执行运算,将得到的结果压入栈顶。
Istore_2:将操作数栈顶元素3pop出来,存储到局部变量表的第2个变量当中,替换掉0。
Iload_2:将局部变量表的第2个变量压入操作数栈栈顶。
Ireturn:将栈顶元素返回出去。

部分问题:
问题:递归为什么会导致Java.lang.StackOverflowError异常

递归过深,栈帧数超过虚拟机栈深度

解决思路:限制递归的次数或直接使用循环的方法去替换递归

问题:
在这里插入图片描述

本地方法栈:
在这里插入图片描述
8.内存模型之线程共享部分
元空间:把类的源数据放置在本地堆内存中。该区域在jdk7以前属于永久代。元空间和永久代都是用来存储class相关信息。包括class的method,field等。元空间和永久代均是方法区的实现。
在这里插入图片描述
在这里插入图片描述
Native-heap就是元空间。 元空间没有字符串常量池,被引入到了堆中。

Java堆:
在这里插入图片描述
9.java内存模型值常考题目
(1)JVM三大性能调优参数:
在这里插入图片描述
一般情况下256就够了。
在这里插入图片描述
(2)java内存模型堆和栈的区别:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Main会分配对应的虚拟机栈,本地栈,以及程序计数器。栈里面会存有String类型的引用参数,保存的是对应于堆中test字符串Object对应的地址引用。还存有本地变量hw保存堆中helloworld这个对象的地址引用。此外,还有局部变量a,保存的是1这个值。以及系统自带的lineNumber,用来记录代码的执行。

  • 26
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值