java 基础知识点1-final与各类引用
1.final,finally,finalize区别
final表示不可修改,finally是保证重点代码一定执行,比如数据库连接池关闭。finalize是object类的一个方法,设计目标保证对象被回收前执行特定的动作,jdk1.9已经不建议使用(因为不知道什么时候执行,执行是否符合预期,另外会拖累垃圾收集)
1.1final
a. final 类不可继承,变量不可修改,方法不可重写
b. final修饰的变量不可变,变量的值一旦不可变,在多线程编程的环境下能保证线程安全,因为变量值不可变,也就不存在多个线程同时竞争资源的问题,代码自然是线程安全的。
c. 理论上final 修饰的方法jvm可以方法内联,提高性能。但是jvm比你想象中要智能,没必要为了提高性能这么做
d. 匿名内部类中使用的外部局部变量为什么只能是final变量,因为内部类访问外部局部变量是拷贝对象的模式(规避外部对象被回收后,内部对象访问不了外部对象的变量),拷贝后内部修改变量会造成数据不一致,final修饰强制不可修改
e. 为什么java 中String类是final的
1.final修饰的类是不可变的,可以缓存hashCode,当做map中的key更快。
2.实现字符串池,节约内存。不会因为一个线程修改影响了其他线程。
3.这里会有一个坑,如果字符串池缓存的字符串非常多,每次young gc都需要扫描这些字符串是否可以被回收,young gc耗时会增加
- java常量池:https://juejin.cn/post/6844903801942441997 https://blog.csdn.net/qq_27093465/article/details/106767042
f. 对于 final 变量,编译器和处理器都要遵守两个重排序规则
构造函数内,对一个 final 变量的写入,与随后把这个被构造对象的引用赋值给一个变量,这两个操作之间不可重排序
首次读一个包含 final 变量的对象,与随后首次读这个 final 变量,这两个操作之间不可以重排序
1.2 finally
try catch 是否资源
2.强引用,软引用,弱引用,虚引用
强引用:new的对象,可达时不可垃圾回收
软引用:gc内存不足的时候,可回收
弱引用:gc的时候回收
虚引用:无法通过引用获取对象,虚引用存在的唯一作用就是当它指向的对象被回收后,虚引用本身会被加入到引用队列中,用作记录它指向的对象已被回收
弱引用场景:threadLocal(https://www.jianshu.com/p/640f2c0ac4b0)



顺带说2句threadLocal
- spring 的事务注解用threadLocal保证是一个数据库连接
- inheritableThreadLocals可用传递父线程的threadLocal的值给子线程
虚引用场景:
堆外内存的释放
虚引用主要被用来 跟踪对象被垃圾回收的状态。通过查看引用队列中是否包含对象所对应的虚引用来判断它是否 即将被垃圾回收,从而采取行动。它并不被期待用来取得目标对象的引用,而目标对象被回收前,它的引用会被放入一个 ReferenceQueue 对象中,从而达到跟踪对象垃圾回收的作用
堆外内存几个问题:
1.零拷贝
正常堆内内存要与io打交道是这样的

堆外内存是这样的:

其实我们多思考一下,这样的优势大吗?其实Channel中IO的操作相对于内存的复制来说是慢很多的,即便我们在读写数据的时候多了两次复制的过程对于整体来说影响是不大的。
那么什么时候就会体现出零拷贝的优势呢?有大量并发io操作,并且io操作是短暂完成的。这时由于节省了大量的内存copy操作,这些节省的时间积累下来也是非常可观的。
netty的底层就是用的零拷贝技术,所以netty能做到很好并发。
2. jvm配置参数:
-XX:+DisableExplicitGC 禁用system.gc,可能导致内存泄露。因为分配堆外内存的时候,发现内存不够,会调用system.gc来主动触发full gc。可以配置-XX:+ExplicitGCInvokesConcurrent参数,不禁止system.gc,但是gc过程不是全过程中断的。