讲一下类加载过程,为什么需要双亲委派
class文件需要加载到虚拟机中之后才能运行和使用,系统加载class类型的文件主要三步,加载->连接->初始化。连接过程又分为三步:验证->准备->解析
加载:1.通过全类名获取定义此类的二进制字节流 2.将字节流所代表的静态存储结构转换为方法区的运行时数据结构 3.在内存中生成一个代表该类的class对象,作为方法区这些数据的访问入口。加载这一步主要是通过类加载器完成的。
验证:确保class文件的字节流中包含的信息符合java虚拟机规范的全部约束,保证这些信息被当作代码运行后不会危害虚拟机自身的安全
准备:正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中分配。这时候进行内存分配的仅包括类变量即静态变量,被static关键字修饰的变量,只与类相关,因此被称为类变量,而不包括实例变量。实例变量会在对象实力化时随着对象一块分配在java堆中
解析阶段:是虚拟机将常量池的符号引用替换为直接引用的过程,解析动作主要针对类或接口,字段,类方法,接口方法,方法类型,方法句柄和调用限定符7类符号引用进行
初始化
初始化阶段是执行初始化方法<clinit>()方法的过程,是类加载的最后一步,这一步JVM才开始真正执行类中定义的java程序代码
卸载阶段
将该类的class对象gc掉,在JVM生命周期内,由jvm自带的类加载器加载的类是不会被卸载的,但是由我们自定义的类加载器加载的类是可能被卸载的
MySQL innodb使用b+树的优缺点
B树的所有节点即存放键也存放数据,而B+树只有叶子节点存放key和data,其他内节点只存放key
B树的叶子节点都是独立的,B+树的叶子节点有一条引用链指向与它相邻的叶子节点。
B树的检索的过程相当于对范围内的每个节点的关键字做二分查找,可能还没有达到叶子节点,检索就结束了,而B+树的检索效率就很稳定,任何查找都是从根节点到叶子节点的过程,叶子节点的顺序检索很明显
在B树中进行范围查询时,首先找到要查找的下限,然后对B树进行中序遍历,直到找到查找的上限;而B+树的范围查询,只需要对链表进行遍历即可
B+树与B树相比,具备更少的IO次数,更稳定的查询效率和更适于范围查询的优势
Redis过期策略
定时删除:在设置key的过期时间时,同时创建一个定时事件,当时间到达时,由事件处理器自动执行key的删除操作
惰性删除:不主动删除过期键,每次从数据库访问key时,都检测key是否过期,如果过期则删除该key
定期删除:每隔一段时间随机从数据库中取出一定数量的key进行检查,并删除其中的过期key
Java中clone方法是深拷贝还是浅拷贝
对于没有重写clone方法的,对象中的引用数据类型只是复制了该引用数据类型的引用,并没有内存空间中开辟空间复制该引用的数据类型,即对该引用数据类型进行了浅拷贝
Linux系统用什么指令查看路由表
ip route
java接口里面可以定义变量么
可以,必须是public static final形式
Java虚引用作用
虚引用必须和引用队列一同使用,作用在于跟踪垃圾回收过程,在对象被收集器回收时收到一个系统通知。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在垃圾回收后,将这个虚引用加入引用队列,在其关联的虚引用出队前,不会彻底销毁该对象,所以可以通过检查引用队列中是否有相应的引用来判断对象是否已经被回收了
红黑树原理
红黑树的特性每个节点或黑或红
根节点是黑色
空叶子节点是黑色
如果一个节点是红色,那么他的子节点是黑色
从任意一个节点出发到空的叶子节点经过的黑节点个数相同
红黑树的基本操作:左旋和右旋
以X为中心,左旋是将X的右子树绕X逆时针旋转,使得X的右子树成为X的父亲
以X为中心,右旋是将X的左子树绕X顺时针旋转,使得X的左子树成为X的父亲
查询复杂度为O(logn)适用于大量查询的场景
epoll边缘触发和水平触发原理
使用边缘触发模式时,当被监控的socket描述符上有可读事件发生时,服务端只会从epoll_wait中苏醒一次,即使进程没有调用read函数从内核读取数据,也依然只苏醒一次,因此程序要保证一次性将内核缓冲区的数据读取完
使用水平触发模式,当被监控的socket上有可读事件发生时,服务器端不断地从epoll_wait中苏醒,直到内核缓冲区数据被read函数读完才结束
两者区别在于水平触发是只要满足事件的条件,比如内核中有数据需要读,就一直不断地吧这个事件传递给用户,而边缘触发是只有第一次满足条件的时候才触发,之后就不会再传递同样的事件了。
如果使用水平触发模式,当内核通知文件描述符可读写时,接下来还可以继续去检测他的状态,看他是否依然可读或可写。所以在收到通知后,没必要一次执行尽可能多的读写操作
如果使用边缘触发模式,I/O事件发生时只会通知一次,而且我们不知道到底读写多少数据,所以在收到通知后应尽可能地读写数据,以免错失读写的机会
Java异常
包括Exception和Error两部分,exception是程序本身可以处理的异常,可以通过catch来进行捕获,exception又分为checked exception受检查异常,必须处理和unchecked exception不受检查异常,可以不处理。Error属于程序无法处理的错误。checked exception即受检查异常,如果受检查异常没有被catch或者throws关键字处理的话,就没办法通过编译。Unchecked exception不受检查异常,即使不处理不受检查异常也可以正常通过编译。其中非受检查异常包括空指针错误,字符串转换为数字格式错误,数组越界错误,算术错误。
什么是工厂模式
public interface AbstractFactory {
Phone makePhone();
}
public class IFactory implements AbstractFactory{
@Override
public Phone makePhone() {
return new IPhone();
}
}
public class XiaomiFactory implements AbstractFactory{
@Override
public Phone makePhone() {
return new MiPhone();
}
}
public class MiPhone implements Phone{
public MiPhone(){
System.out.println("小米手机");
}
}
public class IPhone implements Phone{
public IPhone(){
System.out.println("苹果手机");
}
}
public interface Phone {
}
Java线程状态
初始:新创建一个线程对象,但还没有调用start()方法
运行:java线程中将就绪ready和运行中running两种状态统称为运行。线程对象创建后,其他线程调用了该对象的start方法,该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态。就绪状态的线程在获得CPU事件片后变味运行中状态
阻塞:表示线程阻塞于锁
等待:进入该状态的线程需要等待其他线程作出一些特定动作(通知或者中断)
超时等待:该状态不同于waiting,他可以在指定时间后自行返回
终止:表示该线程已执行完毕
参考资料: