JVM面试题集
1.说一说类加载的详细过程。
答:类加载器加载类到JVM中,分为以下几个步骤:
1)加载:查找并加载类的二进制数据,同时在Java堆中也创建一个java.lang.class类的对象。
2)连接:连接又包含三块内容(验证、准备、初始化)
a.验证:文件格式、元数据、字节码、符号引用验证。
b.准备:为类的静态变量分配内存,并将其初始化为默认值。
c.解析:把类中的符号引用转换为直接引用。
3)初始化:为类的静态变量赋予正确的初始值。
补充:Java的执行机制
先编译后运行→先编译后解释执行→解释又分为解析和加载
2.类加载完以后JVM干了什么?
答:在类加载检查通过后,接下来虚拟机将为新生对象分配内存。
3.讲一讲什么情况下会出现内存溢出和内存泄漏。
答:内存溢出的原因
1)内存泄漏导致堆栈内存不断增大,从而引发内存溢出。
2)大量的jar、class文件加载,装载类的空间不够,从而溢出。
3)nio直接操作内存,内存过大导致溢出。
解决:
1)查看程序是否存在内存泄漏的问题。
2)设置参数加大空间。
3)代码中是否存在死循环或者循环产生过多重复的实例。
4)查看是否使用了nio直接操作内存。
4.简述Java内存模型以及分区,需详细到每个区放什么?
答:JVM分为堆区、栈区和方法区,初始化的对象放在堆里面,引用放在栈里面,class类信息、常量池和静态信息等放在方法区。
栈:栈的结构是栈帧组成的,调用一个方法就压入一帧,帧上面存储局部变量表,操作数栈,方法出口等信息,局部变量表存放的是8大基础类型加上一个应用类型,所以还是一个指向地址的指针。
堆:初始化的对象,成员变量(非static的变量),所有的对象实例和数组都要在堆上分配。
方法区:主要是存储类信息、常量池(static常量和static变量),编译后的代码(字节码)等数据。
本地方法栈:主要为Native方法服务。
程序计数器:记录当前线程执行的行号。
5.简述Java垃圾回收机制。
答:在Java中程序员是不需要显示的区释放一个对象的内存的,而是由虚拟机自行执行。在JVM中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫描那些没有任何引用的对象,并将它们添加到要回收的集合中,进行回收。
6.Java中垃圾收集的算法有哪些?
答:
1)标记清除
这是垃圾收集算法中最基础的,根据名字就可以知道,它的思想就是标记那些要被回收的对象,然后统一回收。这种方法很简单,但是会有两个主要问题:1.效率不高,标记和清除的效率都很低。2.会产生大量不连续的内存碎片,导致以后程序在分配较大的对象时,由于没有充足的连续内存而提前触发一次GC动作。
2)复制算法
为了解决效率问题,复制算法将可用内存按容量划分为相等的两部分,然后每次只使用其中的一块,当一块内存用完时,就将还存活的对象复制到第二块内存上,然后一次性清除完第一块内存,再将第二块上的对象复制到第一块。但是这种方式,内存的代价太高,每次基本上都要浪费一些内存。
于是将该算法进行了改进,内存区域不再是按照1:1去划分,而是将内存划分为8:1:1三部分,较大那份内存交Eden区,其余是两块较小的内存区叫Survivor区。每次都会优先使用Eden区,若Eden区满,就将对象复制到第二块内存区上,然后清除Eden区,如果此时存活的对象太多,以至于Survivor不够时,会将这些对象通过分配担保机制复制到老年代中。(java堆又分为新生代和老年代)
3)标记整理
该算法主要是为了解决标记清除产生大量内存碎片的问题,当对象存活率较高时,也解决了复制算法的效率问题,它的不同之处就是在清除对象的时候,将可回收对象移动到一端,然后清除掉端边界以外的对象,这样就不会产生内存碎片了。
4)分代收集
现在的虚拟机垃圾收集大多采用这种方式,它根据对象的生存周期,将堆分为新生代和老年代。在新生代中,由于对象生存期短,每次回收都会有大量对象死去,那么这时就采用复制算法。老年代里的对象存活率较高,没有额外的空间进行分配担保,所以可以使用标记整理算法或标记清除算法。
7.什么是类加载器?类加载器有哪些?
答:实现通过类的权限定名获取该类的二进制字节流的代码块叫做类加载器。
1)启动类加载器(Bootstrap Class Loader):用来加载Java核心类库,无法被Java程序直接引用。
2)扩展类加载器(Extensions Class Loader):用来加载Java的扩展库。Java虚拟机的实现会提供一个扩展库目录,该类加载器在此目录里面查找并加载Java类。
3)系统类加载器(System Class Loader):根据Java应用的类路径(ClassPath)来加载Java类,一般来说,Java应用的类都是由它来完成加载的。可以通过ClassLoader.getSystemClassLoader()来获取。
4)自定义类加载器:通过继承java.lang.ClassLoader类的方式实现。
数据库面试题集
8.什么是主键、超键、候选键、外键?
答:
主键:数据库表中对存储数据对象予以唯一和完整标识的数据列或属性的组合。一个数据列只能有一个主键,且主键的取值不能缺失,即不能为空值(Null)。
超键:在关系中能唯一标识元素的属性集称为关系模式的超键,一个属性可以作为一个超键,多个属性组合在一起也可以作为一个超键,超键包含候选键和主键。
候选键:最小的超键,即没有冗余元素的超键。
外键:在一个表中存在的另一个表的主键,称此表的外键。
9.简述数据库事务的四个特性及含义。
答:数据库事务Transaction正确执行的四个基本要素:ACID,原子性(Atomicity)、一致性(Correspondence)、隔离性(Isolation)、持久性(Durability)。
原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性:在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
隔离性:隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请求,使得在同一时间仅有一个请求用于同一数据。
持久性:在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会回滚。
10.简述数据库索引的工作原理。
答:数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据,索引的实现通常使用B树及其变种B+树。
在数据之外,数据库系统还维护者满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。
为表设置索引要付出代价,一是增加了数据库的存储空间,二是在插入和修改数据时要花费较多的时间,因为索引也要随之变动。
创建索引的好处:
1)通过创建唯一索引,可以包装数据库表中每一行数据的唯一性。
2)可以大大加快数据的检索速度,这也是创建索引的最主要原因。
3)可以加速表与表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
4)在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
5)通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
创建索引的弊端:
1)创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
2)索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
3)当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
11.简述数据库优化思路。
答:
1)SQL语句优化
a.应尽量避免在where子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
b.应尽量避免在where子句中对字段进行null值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
a)Select id from t where num is null;
b)可以在num上设置默认值0,确保表中num列没有null值,然后查询。
c)Select id from t where num=0;
c.很多时候用exists代替in是一个好的选择。
d.用where子句替换having子句,因为having只会在检索出所有记录之后才对结果集进行过滤。
2)索引优化(上题已经介绍)
3)数据库结构优化
a.范式优化:比如消除冗余节省空间。
b.反范式优化:比如适当加冗余,减少join。
c.拆分表:分区将数据在物理上隔开,不同分区的数据可以指定保存在处于不同磁盘上的数据文件里。这样当对这个表进行查询时,只需要在表分区中进行扫描,而不必进行全表扫描,明显缩短了查询时间,另外处于不同磁盘的分区也将对这个表的数据传输分散在不同的磁盘I/O,一个精心设置的分区可以将数据传输对磁盘I/O竞争均匀的分散开。对数据量大的表可采取此方法,可按自动建表分区。
d.拆分其实又分垂直拆分和水平拆分。案例:简单购物系统暂设计如下表:
a)产品表(数据量10W,稳定)
b)订单表(数据量200W,且有增长趋势)
c)用户表(数据量100W,且有增长趋势)
d)以MySQL为例讲述水平拆分和垂直拆分,MySQL能容纳百万到千万的静态数据。
e)垂直拆分
i.解决问题:表与表之间的io竞争。
ii.不解决问题:单表中数据量增长出现的压力。
iii.方案:把产品表和用户表放到一个server上,订单表单独放到一个server上。
f)水平拆分
i.解决问题:单表中数据量增长出现的压力。
ii.不解决问题:表与表之间的io争夺。
iii.方案:用户表通过性别拆分为男用户表和女用户表,订单表通过已完成和完成中拆分为已完成订单表和未完成订单表,产品表未完成订单放一个server上,已完成订单表和男用户表放一个server上,女用户表放一个server上。
4)服务器硬件优化
买买买,使劲花钱!
来源:https://blog.csdn.net/qq_44906471/article/details/99196715