Java基础(二)

320 阅读6分钟

14. 什么是字节码,好处是什么

app - > jVM(linux/windows) 跨平台

15. Java类加载器

jdk自带:bootstrap ClassLoader 、 ExtClassLoader、AppClassLoader

16. 双亲委托/委派模型

image.png

向上查缓存,向下查找加载路径 好处:安全性,避免用户自己编写的类动态替换java的一些核心类,比如String 避免类的重复加载,JVM区分不同类,不仅仅根据类名,相同的class被不同的classLoader加载就是不同的两个类

17.Java中的异常体系

最顶级父类:Throwable--「 Exception 和 Error (出现OOM内存溢出,程序无法处理的错误) Exception不会导致程序停止,RunTimeException运行时异常(数组下标越界,空指针等情况)和CheckedException检查异常。

18.GC如何判断对象可以被回收

a.引用计数法(python的GC):

每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放计数减1,计数为0时可以回收 缺陷:循环引用,但是效率很高,java并没有采用

b.可达性分析法(java):

GCRoots开始向下开始搜索,搜索所走过的路径引用链,当一个对象到GCRoots没有任何引用链相连,则证明对象不可用,虚拟机可回收。 GCRoots对象有: (1)虚拟机栈中引用的对象 (2)方法区中类的静态属性引用的对象 (3)方法区常量引用对象 (4)本地方法栈JNI(Native方法)引用的对象 2次回收:第一次是经过可达性分析发现没有GCRoot连接的引用链。第二次在由虚拟机自动建立的Finalizer队列中判断是否需要执行finalize()方法 对象编程不可达,GC会判断该对象是否覆盖finalize方法,不建议覆写finalize。

19.线程的生命周期,有哪些状态

a.状态:

创建 、就绪:可运行,Runnable 运行: 阻塞:等待阻塞,同步阻塞(同步锁),其他阻塞 死亡:

20.sleep()、wait()、join()、yield()的区别

锁池:所有需要竞争同步锁的线程都会放在锁池当中,比如当前对象的锁已经被其中一个线程得到,则其他线程需要在这个锁池进行等待,当前线程释放同步锁后锁池中的线程竞争同步锁,当某个线程得到后会进入就绪队列进行等待cpu资源分配。 等待池:wait()方法后,线程会放到等待池当中,等待池的线程是不会去竞争同步锁。只有调用了notify()或者notifyAll()后等待池的线程才会去开始竞争锁,notify()是随机从等待池选出一个线程放到锁池,而notifyAll()是将等待池的所有线程放到锁池当中的

(1)sleep是Thread类中静态本地方法,wait是Object类的本地方法 (2)sleep方法不会释放lock,wait会释放,而且会加入到等待队列中。 (3)sleep不依赖同步器synchronized,但是wait需要依赖synchronized关键字 (4)sleep不需要被唤醒(休眠之后推出阻塞),但是wait需要(不指定时间需要其他地方被别人中断) (5)sleep一般用于当前线程休眠,或者轮询暂停操作,wait则多用于多线程之间通信 (6)sleep让出cpu强制切换上下文,wait不一定,有可能重新竞争到锁继续执行。

yield()执行后线程直接进入就绪状态,马上释放cpu的执行权 join()等待执行完 yield()让出cpu

21.线程安全的理解

不是线程安全,应该是内存安全,JVM的堆是共享内存,可以被所有线程访问 如果多个线程访问同一个对象时,调用对象行为和单线程结果一样则为安全。

堆:进程和线程共有的空间,分全局堆和局部堆,全局堆是所有没有分配空间,局部堆是用户分配的空间 堆在操作系统对进程初始化的时候分配,运行过程中可以额外申请,用完还给系统,不然存在内存泄漏。

栈:每个线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈相互独立,因此,栈是线程安全的。操作系统在切换线程的时候自动切换栈,栈空间不需要在高级语言里面显式分配和释放

造成线程安全的潜在原因:在每个进程内存空间中都会有一块特殊的公共区域,通常称为堆(内存),进程内的所有线程都可以访问到该内存区域。

22. Thread和Runable的区别

Thread(类)实现了Runable(接口) 共享资源都能操作 继承关系

23. 守护线程的理解

守护线程:为所有非守护线程提供服务的线程,任何一个守护线程都是整个JVM中的所有非守护线程的守护线程 依赖于进程,用户线程都结束,守护线程才结束,不靠谱 其终止不可靠 GC垃圾回收线程:经典的守护线程 不能把正在运行的线程设置为守护线程 在Daemon线程中产生的新线程也是守护线程 后台线程

24. ThreadLocal的原理和使用场景

每一个Thread对象包含一个ThreadLocalMap类型的成员变量threadLocals,其存储本线程中所有ThreadLocal对象及其对应的值。

ThreadLocalMap容器线程私有,不存在线程安全问题 线程间的数据隔离 事务操作,用于存储线程事务信息 数据库连接,session信息

25. ThreadLocal内存泄露原因,以及如何避免

controller层-> service层 -> dao层

不再被使用的对象或者变量占用的内存不能被回收,就是内存泄露,最终会导致OOM OOM-内存不够

强虚软弱引用 new / 反射 -》 创建对象 都是强引用,不会被垃圾回收器回收,当内存空间不足,java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不回收这种对象 如果想取消强引用和某个对象之间的关联,可以显式的将引用赋值为null,这样可以使JVM在合适的时间就会回收该对象。 WeakReference弱引用:JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。可以在缓存中使用弱引用。

threadLocal调用后完成,使用remove方法清空数据