Java基础
JAVA基础
1.jvm什么时候会出现栈内存溢出
->首先要理解栈里面存放的什么(栈帧),存放的是每个方法运行时候都会创建一个栈帧,栈帧里面存的是的
局部变量表
操作数栈
动态链接(多态)
返回地址
只有到栈里面的栈帧占用空间过大就会导致内存溢出,情景:方法的递归调用
2.如果让你写一段栈溢出代码你会怎么写,一个栈大概有多大,为什么?每个线程都会有这样的一个栈么?
public class Demo{
public static void foreach(){
int age = 10;
foreach();
}
public static void main(String[] args){
foreach();
}
}
一个栈通常只有几百K,-Xss可以分配栈的内存大小,栈不需要太大内存,因为栈的数据结构决定的,每个方法执行完后,都会出栈,不再占据内存
每个线程都会有一个栈的,虚拟机栈和本地方法栈都是线程私有的,而堆,程序计数器都是线程共享的
3.JVM一次完整的GC是怎么样的,怎么样提升至老年代
首先要了解的是JVM里面运行时内存区域-》堆空间-新生代,老年代,和永久代(jdk8后改为了元空间)
新生代又分为伊甸园区,survivor0和survivor1区(in区和out区)
大部分的对象创建都是出生的伊甸园区,当Eden区触发minorGC时,如果对象没有被回收就会存在在survivor0区,如果存放不下就会被直接提升至老年代内存中
一般minorGC触发15次左右就会被survivor0或1区的时候,就会提升至老年代
如果老年代存放不下,就会触发了majorGC,回收老年代的空闲对象,
当老年代和新生代内存不足时,就会出现FullGC,然后STW
4.介绍GC的回收机制和分代回收策略(分代回收见3)
GC的回收机制:
以应用程序root为顶点,遍历应用程序在heap中分配的所有对象,通过识别对象是否已经被root或者其他对象引用,然后进行回收。
5.java中几种引用关系。它们的区别是什么。
1.强引用 -触发gc也不会被回收
2.软引用 -内存不足的时候会被回收
3.弱引用 -触发gc就回收
4.虚引用 -用来检测垃圾回收触发动作的,没啥时候应用场景
6.GC算法有哪些?它们的特点是什么
引用计数法:无法解决循环引用的问题
回收算法:1.标记-清除算法(先标记后清除,需要遍历两次,内存空间不连续,会有内存碎片)
2.复制算法(两块内存,重新拷贝,占用内存)
3.标记-压缩算法(效率低)
检测回收:1.引用计数法 2.可达性算法
7.如何判断一个对象是否被回收,有哪些GC算法,实际上虚拟机使用的最多的是什么GC算法
1、可达性算法
2、引用计数法-通过判断对象的引用链是否可达来决定对象是否可以被回收
用到的最多-分代回收算法
8.jvm的内存结构
ClassLoader
.class ------------------>加载到内存中
运行时数据区
-------------------------------------------
|堆 方法区 本地方法栈 虚拟机栈 程序计数器 |
-------------------------------------------
|| ||
执行引擎<-------本地接口<-------本地库
-类的生命周期
1.加载
2.链接(验证-准备-解析)
3.初始化
4.使用
5.卸载
9.jvm dvm art的区别
dvm(dalvik)和art都不是jvm的一种,并没有遵循jvm规范
dvm和jvm的区别
1.基于的架构不同,jvm基于栈,dvm是基于寄存器的
2.执行的字节码不同,jvm是加载.class文件,dvm加载的是.dex文件
3.dvm运行在有限的内存中同时运行多个进程
ART(android run time) 用来替换dalvik虚拟机
ART和dalvik的区别:
1.ART对垃圾回收机制进行了改进
2.ART支持64位并兼容32位cpu,dalvik只支持32位cpu
3.ART运行时的堆空间划分和dalvik不一样(垃圾收集的方式和策略不一样,Android 8后,采用的是并发压缩算法)
DVM使用的是标记-清除算法
ART采用了多种垃圾算法 - CMS 并发压缩算法 -分代收集思想的垃圾算法
10.描述GC机制。class会不会回收,用不到的class怎么回收
--不会
11.StackOverflow和OOM的区别
StackOverflows是栈溢出-只存在于栈中
OOM是内存溢出-堆空间,栈和方法区都有可能出现内存溢出的情况
12.请描述new一个对象的流程
1.判断该对象是否已经被ClassLoader加载过(经历装载,链接,初始化等过程)
2.对象内存的分配-指针碰撞,空闲列表
3.处理并发安全的问题-CAS
4.初始化分配到的内存
5.设置对象的对象头
6.调用对象的init方法进行初始化
13.Java对象会不会分配到栈上
有可能的,有一个叫栈上分配 --->将线程私有的对象打散分配在栈上
//user的作用域超出了函数setUser的范围,是逃逸对象
//当函数结束调用时,不会自行销毁user
private User user;
public void setUser(){
user = new User();
user.setId(1);
user.setName("blueStarWei");
}
//u只在函数内部生效,不是逃逸对象 重点重点-栈上分配
//当函数调用结束,会自行销毁对象u
public void createUser(){
User u = new User();
u.setId(2);
u.setName("JVM");
}
14.String,StringBuilder,StringBuffer的区别
String被final修饰,不可修改,使用常量存放在常量池里,new的话存放在堆
StringBuilder,线程不安全,效率高
StringBuffer,线程安全,效率低
15.String在内存中如何创建的
对于字符串:其对象的引用都是存储在栈中的,
如果是【编译期已经创建好(直接用双引号定义的)的就存储在常量池中】,
如果是【运行期(new出来的)才能确定的就存储在堆中】。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。
16.String为什么设计成不可修改的
线程安全,实现常量池
17.final,finally,finalize的区别
final。修饰符,被修饰的对象不能被继承,被修饰的方法不能被重写,被修饰的变量不能在被修改
finally。适用于try-catch-finally,try-resource-finally,确保这段语句会被执行(特殊情况下不会执行,如System.exit(0))
finalize。对象被回收的时候释放一些资源,需要实现finalize
18.抽象类和接口的区别
抽象类只能单继承,接口可以多实现
抽象类有构造方法,接口没有
抽象类能实现方法,接口不行
接口声明的变量会自动被final修饰,不允许修改
抽象类可以实现接口方法,可以不重写接口方法
19.重载和重写的区别
重载是指相同的方法名,拥有不同的方法参数
重写是指子类继承父类的方法,并重新定义方法的实现
20.什么是值传递和引用传递,JAVA是值传递还是引用传递
按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值
只有基本类型和按照下面这种定义方式的String是按值传递,其它的都是按引用传递。
21.异常的分类
Throwable
-Exception
-Error
22.equals 和 hashcode 的关系?
如果对象相同时,那么hashcode一定相等
如果两个hashcode相同,那么这两个对象也不一定相同
23.什么是三次握手
三次握手(主要是为了验证各个端的正常使用)
第一次 客户端发送seq 确定了 客户端的 发送能力 和服务端的接收能力
第二次 服务端返回 seq 和 ack 客户端确认了自己的发送能力和接收能力
第三次 客户端发送 ack 服务端确定了自己的发送能力
由此进行数据传输

浙公网安备 33010602011771号