【155期】面试官:你遇到过log4j2线程阻塞的场景吗,如何解决呢?
共 3114字,需浏览 7分钟
·
2021-03-15 00:13
阅读本文大概需要 2.8 分钟。
来自:cnblogs.com/yeyang/p/10400486.html
背景
https://blog.fliaping.com/a-high-concurrency-problem-of-log4j2/
大量线程block原因
首先会持有锁。
调用findLoadedClass看下是否类已经被加载过了
如果类没被加载过,根据双亲委派模型去加载类。
sun.reflect.GeneratedMethodAccessor<N>
的类,这个类无法通过ClassLoader.loadClass方法加载(为什么无法通过ClassLoader.loadClass加载?因为JVM内部自定义一个加载器DelegatingClassLoader来加载这个类,这导致应用类加载器 Launcher$AppClassLoader
找不到它)。关于JVM对反射调用的优化
JNI:使用native方法进行反射操作。
pure-Java:生成bytecode进行反射操作,即生成类
sun.reflect.GeneratedMethodAccessor<N>
,它是一个被反射调用方法的包装类,代理不同的方法,类后缀序号会递增。这种方式第一次调用速度较慢,较之第一种会慢3-4倍,但是多次调用后速度会提升20倍
-Dsun.reflect.inflationThreshold=<value>
value默认为15,即反射调用某个方法15次后,会由JNI的方式变为pure-java的方式-Dsun.reflect.noInflation=true
默认为false。当设置为true时,表示在第一次反射调用时,就转为pure-java的方式
https://rednaxelafx.iteye.com/blog/548536
public class TestMethodInvoke {
public static void main(String[] args) throws Exception {
Class<?> clz = Class.forName("A");
Object o = clz.newInstance();
Method m = clz.getMethod("foo", String.class);
for (int i = 0; i < 100; i++) {
m.invoke(o, Integer.toString(i));
}
}
}
public class A {
public void foo(String name) {
System.out.println("Hello, " + name);
}
}
如何关闭JVM对反射调用的优化?
$ java -Dsun.reflect.inflationThreshold=2147483647 MyApp
推荐阅读:
【154期】面试官:你能说说 Elasticsearch 查询数据的工作原理是什么吗?
【153期】面试官:谈谈常用的Arraylist和Linkedlist的区别
【152期】面试官:你能说出MySQL主从复制的几种复制方式吗?
微信扫描二维码,关注我的公众号
朕已阅