Java面试必考题
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java面试必考题,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含21578字,纯文字阅读大概需要31分钟。
内容图文
![Java面试必考题](/upload/InfoBanner/zyjiaocheng/641/0dc531c8137d43e0ad07eadce27090b4.jpg)
1. JDK 和 JRE 有什么区别?
-
JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的开发环境和运行环境。
-
JRE:Java Runtime Environment 的简称,java 运行环境,为 java 的运行提供了所需环境。
2. == 和 equals 的区别是什么?
== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,只是很多类重新了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。
3. 两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?
不对,两个对象的 hashCode()相同,equals()不一定 true。
4. final 在 java 中有什么作用?
-
final 修饰的类叫最终类,该类不能被继承。
-
final 修饰的方法不能被重写。
-
final 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。
5. java 中的 Math.round(-1.5) 等于多少?
等于 -1,因为在数轴上取值时,中间值(0.5)向右取整,所以正 0.5 是往上取整,负 0.5 是直接舍弃。
6. String 属于基础的数据类型吗?
String 不属于基础类型,基础类型有 8 种:byte、boolean、char、short、int、float、long、double,而 String 属于对象。
7. java 中操作字符串都有哪些类?
操作字符串的类有:String、StringBuffer、StringBuilder。
8. String 类的常用方法都有那些?
-
indexOf():返回指定字符的索引。
-
charAt():返回指定索引处的字符。
-
replace():字符串替换。
-
trim():去除字符串两端空白。
-
split():分割字符串,返回一个分割后的字符串数组。
-
getBytes():返回字符串的 byte 类型数组。
-
length():返回字符串长度。
-
toLowerCase():将字符串转成小写字母。
-
toUpperCase():将字符串转成大写字符。
-
substring():截取字符串。
-
equals():字符串比较。
9. 普通类和抽象类有哪些区别?
-
普通类不能包含抽象方法,抽象类可以包含抽象方法。
-
抽象类不能直接实例化,普通类可以直接实例化。
10. 接口和抽象类有什么区别?
-
实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。
-
构造函数:抽象类可以有构造函数;接口不能有。
-
main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。
-
实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
-
访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。
11.简单来说:继承是子类获得父类的成员,除protected;
重写是继承后重写实现父类的方法
重载是在一个类中使用一系列名字不同的方法
多态是父类使用子类的方法 父类 对象 = new 子类();
11. java 中 IO 流分为几种?
按功能来分:输入流(input)、输出流(output)。
按类型来分:字节流和字符流。
12. java 容器都有哪些?
常用容器的图录:
13. List、Set、Map 之间的区别是什么?
14. HashMap 和 Hashtable 有什么区别?
-
hashMap去掉了HashTable 的contains方法,但是加上了containsValue()和containsKey()方法。
-
hashTable同步的,而HashMap是非同步的,效率上逼hashTable要高。
-
hashMap允许空键值,而hashTable不允许。
15. 如何决定使用 HashMap 还是 TreeMap?
对于在Map中插入、删除和定位元素这类操作,HashMap是最好的选择。然而,假如你需要对一个有序的key集合进行遍历,TreeMap是更好的选择。
基于你的collection的大小,也许向HashMap中添加元素会更快,将map换为TreeMap进行有序key的遍历。
16. Array 和 ArrayList 有何区别?
-
Array可以容纳基本类型和对象,而ArrayList只能容纳对象。
-
Array是指定大小的,而ArrayList大小是固定的。
-
Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。
17. 并行和并发有什么区别?
-
并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。
-
并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。
-
在一台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务。如hadoop分布式集群。
所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。
18. 线程和进程的区别?
简而言之,进程是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线程。进程在执行过程中拥有独立的内存单元,而多个线程共享内存资源,减少切换次数,从而效率更高。
线程是进程的一个实体,是cpu调度和分派的基本单位,是比程序更小的能独立运行的基本单位。同一进程中的多个线程之间可以并发执行。
19. 创建线程有哪几种方式?
①. 继承Thread类创建线程类
-
定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。
-
创建Thread子类的实例,即创建了线程对象。
-
调用线程对象的start()方法来启动该线程。
②. 通过Runnable接口创建线程类
-
定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
-
创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
-
调用线程对象的start()方法来启动该线程。
③. 通过Callable和Future创建线程
-
创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
-
创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
-
使用FutureTask对象作为Thread对象的target创建并启动新线程。
-
调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
20. 线程有哪些状态?
线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。
-
创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。
-
就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。
-
运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
-
阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。
-
死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪
21. sleep() 和 wait() 有什么区别?
sleep():方法是线程类(Thread)的静态方法,让调用线程进入睡眠状态,让出执行机会给其他线程,等到休眠时间结束后,线程进入就绪状态和其他线程一起竞争cpu的执行时间。
因为sleep() 是static静态的方法,他不能改变对象的机锁,当一个synchronized块中调用了sleep() 方法,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象。
wait():wait()是Object类的方法,当一个线程执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放对象的机锁,使得其他线程能够访问,可以通过notify,notifyAll方法来唤醒等待的线程
22. notify()和 notifyAll()有什么区别?
-
如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。
-
当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争。
-
优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。
23. 线程的 run()和 start()有什么区别?
每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体。通过调用Thread类的start()方法来启动一个线程。
start()方法来启动一个线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码; 这时此线程是处于就绪状态, 并没有运行。 然后通过此Thread类调用方法run()来完成其运行状态, 这里方法run()称为线程体,它包含了要执行的这个线程的内容, Run方法运行结束, 此线程终止。然后CPU再调度其它线程。
run()方法是在本线程里的,只是线程里的一个函数,而不是多线程的。 如果直接调用run(),其实就相当于是调用了一个普通函数而已,直接待用run()方法必须等待run()方法执行完毕才能执行下面的代码,所以执行路径还是只有一条,根本就没有线程的特征,所以在多线程执行时要使用start()方法而不是run()方法。
24. 什么是死锁?
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。是操作系统层面的一个错误,是进程死锁的简称,最早在 1965 年由 Dijkstra 在研究银行家算法时提出的,它是计算机操作系统乃至整个并发程序设计领域最难处理的问题之一。
25. 怎么防止死锁?
死锁的四个必要条件:
-
互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源
-
请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放
-
不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放
-
环路等待条件:是指进程发生死锁后,若干进程之间形成一种头尾相接的循环等待资源关系
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之 一不满足,就不会发生死锁。
理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和 解除死锁。
26. jsp 有哪些内置对象?作用分别是什么?
JSP有9个内置对象:
-
request:封装客户端的请求,其中包含来自GET或POST请求的参数;
-
response:封装服务器对客户端的响应;
-
pageContext:通过该对象可以获取其他对象;
-
session:封装用户会话的对象;
-
application:封装服务器运行环境的对象;
-
out:输出服务器响应的输出流对象;
-
config:Web应用的配置对象;
-
page:JSP页面本身(相当于Java程序中的this);
-
exception:封装页面抛出异常的对象。
27. session 和 cookie 有什么区别?
-
由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session.典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。这个Session是保存在服务端的,有一个唯一标识。在服务端保存Session的方法很多,内存、数据库、文件都有。集群的时候也要考虑Session的转移,在大型的网站,一般会有专门的Session服务器集群,用来保存用户会话,这个时候 Session 信息都是放在内存的,使用一些缓存服务比如Memcached之类的来放 Session。
-
思考一下服务端如何识别特定的客户?这个时候Cookie就登场了。每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。有人问,如果客户端的浏览器禁用了 Cookie 怎么办?一般这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。
-
Cookie其实还可以用在一些方便用户的场景下,设想你某次登陆过一个网站,下次登录的时候不想再次输入账号了,怎么办?这个信息可以写到Cookie里面,访问网站的时候,网站页面的脚本可以读取这个信息,就自动帮你把用户名给填了,能够方便一下用户。这也是Cookie名称的由来,给用户的一点甜头。所以,总结一下:Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。
28. 说一下 session 的工作原理?
其实session是一个存在服务器上的类似于一个散列表格的文件。里面存有我们需要的信息,在我们需要用的时候可以从里面取出来。类似于一个大号的map吧,里面的键存储的是用户的sessionid,用户向服务器发送请求的时候会带上这个sessionid。这时就可以从中取出对应的值了。
29. 简述 tcp 和 udp的区别?
-
TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接。
-
TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付。
-
Tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。
-
UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
-
每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信。
-
TCP对系统资源要求较多,UDP对系统资源要求较少。
30. tcp 为什么要三次握手,两次不行吗?为什么?
为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤。
如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认。
31. 说一下 tcp 粘包是怎么产生的?
①. 发送方产生粘包
采用TCP协议传输数据的客户端与服务器经常是保持一个长连接的状态(一次连接发一次数据不存在粘包),双方在连接不断开的情况下,可以一直传输数据;但当发送的数据包过于的小时,那么TCP协议默认的会启用Nagle算法,将这些较小的数据包进行合并发送(缓冲区数据发送是一个堆压的过程);这个合并过程就是在发送缓冲区中进行的,也就是说数据发送出来它已经是粘包的状态了。
②. 接收方产生粘包
接收方采用TCP协议接收数据时的过程是这样的:数据到底接收方,从网络模型的下方传递至传输层,传输层的TCP协议处理是将其放置接收缓冲区,然后由应用层来主动获取(C语言用recv、read等函数);这时会出现一个问题,就是我们在程序中调用的读取数据函数不能及时的把缓冲区中的数据拿出来,而下一个数据又到来并有一部分放入的缓冲区末尾,等我们读取数据时就是一个粘包。(放数据的速度 > 应用层拿数据速度)
32. OSI 的七层模型都有哪些?
-
应用层:网络服务与最终用户的一个接口。
-
表示层:数据的表示、安全、压缩。
-
会话层:建立、管理、终止会话。
-
传输层:定义传输数据的协议端口号,以及流控和差错校验。
-
网络层:进行逻辑地址寻址,实现不同网络之间的路径选择。
-
数据链路层:建立逻辑连接、进行硬件地址寻址、差错校验等功能。
-
物理层:建立、维护、断开物理连接。
33. get 和 post 请求有哪些区别?
-
GET在浏览器回退时是无害的,而POST会再次提交请求。
-
GET产生的URL地址可以被Bookmark,而POST不可以。
-
GET请求会被浏览器主动cache,而POST不会,除非手动设置。
-
GET请求只能进行url编码,而POST支持多种编码方式。
-
GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
-
GET请求在URL中传送的参数是有长度限制的,而POST么有。
-
对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
-
GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
-
GET参数通过URL传递,POST放在Request body中。
34.设计模式
单例模式
getInstance是一个函数,在java中,可以使用这种方式使用单例模式创建类的实例,所谓单例模式就是一个类有且只有一个实例,不像object ob=new object();的这种方式去实例化后去使用。
简单点说,就是一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取它们的实例。
getInstance()的返回值是一个对象的引用,并不是一个新的实例,所以不要错误的理解成多个对象。单例模式实现起来也很容易,直接看demo吧
1 public static DBConnect instance; 2 3 public static DBConnect getInstance(){ 4 5 if(instance == null){ 6 7 instance = new DBconnect(); 8 9 } 10 11 return instance; 12 13 }
总的来说:这是单例模式,一般用于比较大,复杂的对象,只初始化一次,应该还有一个private的构造函数,使得不能用new来实例化对象,只能调用getInstance方法来得到对象,而getInstance保证了每次调用都返回相同的对象。
详细解释一下:对象的实例化方法,也是比较多的,最常用的方法是直接使用new,而这是最普通的,如果要考虑到其它的需要,如单实例模式,层次间调用等
观察者模式
对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
装饰者模式
对已有的业务逻辑进一步的封装,使其增加额外的功能,如Java中的IO流就使用了装饰者模式,用户在使用的时候,可以任意组装,达到自己想要的效果。
工厂模式
简单工厂模式:一个抽象的接口,多个抽象接口的实现类,一个工厂类,用来实例化抽象的接口
1 // 抽象产品类 2 abstract class Car { 3 public void run(); 4 5 public void stop(); 6 } 7 8 // 具体实现类 9 class Benz implements Car { 10 public void run() { 11 System.out.println("Benz开始启动了。。。。。"); 12 } 13 14 public void stop() { 15 System.out.println("Benz停车了。。。。。"); 16 } 17 } 18 19 class Ford implements Car { 20 public void run() { 21 System.out.println("Ford开始启动了。。。"); 22 } 23 24 public void stop() { 25 System.out.println("Ford停车了。。。。"); 26 } 27 } 28 29 // 工厂类 30 class Factory { 31 public static Car getCarInstance(String type) { 32 Car c = null; 33 if ("Benz".equals(type)) { 34 c = new Benz(); 35 } 36 if ("Ford".equals(type)) { 37 c = new Ford(); 38 } 39 return c; 40 } 41 } 42 43 public class Test { 44 45 public static void main(String[] args) { 46 Car c = Factory.getCarInstance("Benz"); 47 if (c != null) { 48 c.run(); 49 c.stop(); 50 } else { 51 System.out.println("造不了这种汽车。。。"); 52 } 53 54 } 55 56 }
35. 数据库的三范式是什么?
-
第一范式:强调的是列的原子性,即数据库表的每一列都是不可分割的原子数据项。(确保每列保持原子性)
-
第二范式:要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性。(确保表中的每列都和主键相关)
-
第三范式:任何非主属性不依赖于其它非主属性。(确保每列都和主键列直接相关,而不是间接相关)
36.varchar比char的好处在于varchar型是可变长度
37. mysql 的内连接、左连接、右连接有什么区别?
内连接关键字:inner join;左连接:left join;右连接:right join。
内连接是把匹配的关联数据显示出来;左连接是左边的表全部显示出来,右边的表显示出符合条件的数据;右连接正好相反。
38. mysql 索引是怎么实现的?
索引是满足某种特定查找算法的数据结构,而这些数据结构会以某种方式指向数据,从而实现高效查找数据。
具体来说 MySQL 中的索引,不同的数据引擎实现有所不同,但目前主流的数据库引擎的索引都是 B+ 树实现的,B+ 树的搜索效率,可以到达二分法的性能,找到数据区域之后就找到了完整的数据结构了,所有索引的性能也是更好的。
39. 说一下乐观锁和悲观锁?
-
乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。
-
悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。
40. 如何做 mysql 的性能优化?
-
为搜索字段创建索引。
-
避免使用 select *,列出需要查询的字段。
-
垂直分割分表。
-
选择正确的存储引擎。
41. redis 是什么?都有哪些使用场景?
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
Redis 使用场景:
-
数据高并发的读写
-
海量数据的读写
-
对扩展性要求高的数据
42. redis 有哪些功能?
-
数据缓存功能
-
分布式锁的功能
-
支持数据持久化
-
支持事务
-
支持消息队列
43. 说一下 jvm 的主要组成部分?及其作用?
-
类加载器(ClassLoader)
-
运行时数据区(Runtime Data Area)
-
执行引擎(Execution Engine)
-
本地库接口(Native Interface)
组件的作用: 首先通过类加载器(ClassLoader)会把 Java 代码转换成字节码,运行时数据区(Runtime Data Area)再把字节码加载到内存中,而字节码文件只是 JVM 的一套指令集规范,并不能直接交个底层操作系统去执行,因此需要特定的命令解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行,而这个过程中需要调用其他语言的本地库接口(Native Interface)来实现整个程序的功能。
44. 说一下 jvm 运行时数据区?
-
程序计数器
-
虚拟机栈
-
本地方法栈
-
堆
-
方法区
有的区域随着虚拟机进程的启动而存在,有的区域则依赖用户进程的启动和结束而创建和销毁。
47. 说一下堆栈的区别?
1. 栈内存存储的是局部变量而堆内存存储的是实体;
2. 栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;
3. 栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。
48. 队列和栈是什么?有什么区别?
-
队列和栈都是被用来预存储数据的。
-
队列允许先进先出检索元素,但也有例外的情况,Deque 接口允许从两端检索元素。
-
栈和队列很相似,但它运行对元素进行后进先出进行检索。
49. 说一下类加载的执行过程?
类加载分为以下 5 个步骤:
-
加载:根据查找路径找到相应的 class 文件然后导入;
-
检查:检查加载的 class 文件的正确性;
-
准备:给类中的静态变量分配内存空间;
-
解析:虚拟机将常量池中的符号引用替换成直接引用的过程。符号引用就理解为一个标示,而在直接引用直接指向内存中的地址;
-
初始化:对静态变量和静态代码块执行初始化工作。
50. 怎么判断对象是否可以被回收?
一般有两种方法来判断:
-
引用计数器:为每个对象创建一个引用计数,有对象引用时计数器 +1,引用被释放时计数 -1,当计数器为 0 时就可以被回收。它有一个缺点不能解决循环引用的问题;
-
可达性分析:从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是可以被回收的
51.JVM的垃圾回收机制
GC是JVM的垃圾回收机制,当实例化一个Java对象是时,JVM会对该对象分得一份内存,对象不使用了之后,JVM会自动回收该内存块,降低内存溢出的风险
方式:1.计数:对象创建或被引用时,会增加计数,对象为空时,减少计数;直到计数为0时,便回收内存块
2.从GC的根部队整个对象向下进行搜索,搜索过的路为引用链,当一个对象到GC roots 没有任何引用链相连时,证明该对象是可以被回收的
52. 说一下 jvm 有哪些垃圾回收算法?
-
标记-清除算法
-
标记-整理算法
-
复制算法
-
分代算法
53. 说一下 jvm 有哪些垃圾回收器?
-
Serial:最早的单线程串行垃圾回收器。
-
Serial Old:Serial 垃圾回收器的老年版本,同样也是单线程的,可以作为 CMS 垃圾回收器的备选预案。
-
ParNew:是 Serial 的多线程版本。
-
Parallel 和 ParNew 收集器类似是多线程的,但 Parallel 是吞吐量优先的收集器,可以牺牲等待时间换取系统的吞吐量。
-
Parallel Old 是 Parallel 老生代版本,Parallel 使用的是复制的内存回收算法,Parallel Old 使用的是标记-整理的内存回收算法。
-
CMS:一种以获得最短停顿时间为目标的收集器,非常适用 B/S 系统。
-
G1:一种兼顾吞吐量和停顿时间的 GC 实现,是 JDK 9 以后的默认 GC 选项。
54. 说一下 jvm 调优的工具?
JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具。
-
jconsole:用于对 JVM 中的内存、线程和类等进行监控;
-
jvisualvm:JDK 自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等。
55. 常用的 jvm 调优的参数都有哪些?
-
-Xms2g:初始化推大小为 2g;
-
-Xmx2g:堆最大内存为 2g;
-
-XX:NewRatio=4:设置年轻的和老年代的内存比例为 1:4;
-
-XX:SurvivorRatio=8:设置新生代 Eden 和 Survivor 比例为 8:2;
-
–XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器组合;
-
-XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器组合;
-
-XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器组合;
-
-XX:+PrintGC:开启打印 gc 信息;
-
-XX:+PrintGCDetails:打印 gc 详细信息。
最后非常感谢大佬的整理,原文链接一共200题:https://www.zhihu.com/question/27858692/answer/787505434
https://mp.weixin.qq.com/s/MXKACpJKLMxep5bXO3EHhw
内容总结
以上是互联网集市为您收集整理的Java面试必考题全部内容,希望文章能够帮你解决Java面试必考题所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。