文章参考的是javaGuide,
https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/multi-thread/2020%E6%9C%80%E6%96%B0Java%E5%B9%B6%E5%8F%91%E8%BF%9B%E9%98%B6%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98%E6%80%BB%E7%BB%93.md
这里记录属于个人的查漏补缺,如果小伙伴需要更加全面和详细的资料,请看上面的链接呦!
1、为什么要将永久代替换为元空间呢?
永久代有一个JVM本身设置固定大小上限,无法进行调整。元空间使用的是直接内存,受本机可用内存的限制,虽然也会溢出,但是几率小。
2、对象的创建过程
1、类加载检查
当虚拟机遇到一条new指令时,首先会检查这个指令的参数能够在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否为加载、解析、初始化过,如果没有,就先执行类加载过程。
2、分配内存
检查通过之后,为新生对象分配内存。分配内存的方式有两种:指针碰撞、空闲列表。选择那种方式取决于java堆是否规整。
3、初始化为0
将分配的内存空间初始化为0.目的是保证对象的实例字段不赋初值也可以使用。
4、设置对象头
设置这个对象属于哪个类的实例,gc分代年龄等。
5、执行init方法
3、GC调优原则
gc调优的目的是、
- 将转移到老年代的对象数量降低到最小;
-
- 减少gc的执行时间。
调优策略:
- 减少gc的执行时间。
- 首先在新生代中分配对象。因为full gc的代价远远大于minor gc的代价。实际项目中可以根据日志分析新生代空间大小分配是否合理,通过“-Xmn”命令调节新生代大小。
- 大对象进入老年代。大对象会占据很大的空间,那样后面的新生对象分配就内存不足了,会频繁minor gc。
- 长期存活的对象进入老年代。
- 合理设置进入老年代对象的年龄。
4、如何判断一个常量是废弃常量?
假如在字符串常量池中存在字符串“abc”,如果当前没有任何string对象引用该字符串常量的话,就说明常量“abc”是废弃常量。
如何判断一个类是无用类?
方法区中主要回收的是无用的类。无用的类需要满足下面三个条件:
- 该类的所有实例都被回收了
- 加载该类的classloader已经被回收
- 该类对应的java.lang.class对象没有在任何地方被引用,无法通过反射访问该类的方法。
满足这三个条件可以被回收,但,不一定必然回收。
5、G1收集器
G1是一款面向服务器的垃圾收集器,可以满足gc停顿时间要求的同时还提高了系统吞吐量。
G1收集器在后台维护了一个优先列表,每次根据允许的收集时间,优先选择回收价值最大的region(它将内存区域划分成几个region)。这种使用region和优先级的回收方式,保证了g1的收集效率。
6、JDK监控和故障处理工具
- jps:查看所有java进程
- jmap:生成堆转储快照
- jstack:生成线程快照。主要目的是定位线程长时间出现停顿的原因。比如:线程死锁、死循环、请求外部资源导致的长时间等待等。
7、JDK可视化分析工具
jconsole、visualvm
作用:
- 内存监控:显示当前内存的详细信息。
- 线程监控:类似于jstack命令。
8、双亲委派模型
原理就不说了。
好处:保证了Java程序的稳定运行,可以避免类的重复加载,也保证了java的核心API不被篡改。
避免类的重复加载解释:jvm区分类的不同方式不仅仅根据类名,相同的类文件被不同的类加载器加载产生的是两个不同的类。
如果不想使用双亲委派模型?
自定义类加载器的话,需要继承classLoader。如果不想打破双亲委派模型,就重写classloader类中的findClass()方法,无法被父类加载器加载的方法会通过这个方法加载。如果打破模型的话,就重写loadclass()方法。