Java软件工程师 2018-10-15 15:24 采纳率: 50%
浏览 863
已采纳

是什么导致一个类被clinit了多次?

这是我的Springboot启动的的图
图片说明
如图所示:
com.essence.framework.support.jdbc.JdbcUtil这个类之前被初始化过一次,里面的静态属性已经被赋值了,但是后来调用的时候发现,静态属性值莫名变成null了。
于是我把调用堆栈信息打印了出来。
发现该类被clinit了两次!第一次是我人为控制初始化的,自然属性值什么的都赋值了。
但是为什么第二次使用的时候,又被clinit了呢?

  • 写回答

3条回答 默认 最新

  • Java软件工程师 2018-10-16 05:34
    关注

    关于clinit是这么解释的:
     --引文--
    虚拟机会保证一个类的clinit()方法在多线程环境中被正确的加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的clinit()方法,其他线程都需要阻塞等待,直到活动线程执行clinit()方法完毕。需要注意的是,其他线程虽然会被阻塞,但如果执行clinit()方法的那条线程退出clinit()方法后,其他线程唤醒后不会再次进入clinit()方法。同一个类加载器下,一个类型只会初始化一次。

    为什么我的JdbcUtil被clinit了两次。

    ----已解决,完结撒花---
    错误原因,我引入了devtools依赖。
    错误分析:我在jdbcUtil中添加static代码块,在其中输出了classloader。发现:第一次加载时候的classloader为:org.springframework.boot.devtools.restart.classloader.RestartClassLoader,第二次加载的时候的classloader为:sun.misc.Launcher$AppClassLoader。我的JdbcUtil第一次初始化静态全局变量是在ServletContextListener监听中,该监听中的所有类都是由devtools的RestartClassLoader加载的。后面使用jdbcUtil的时候,却是用AppClassLoader加载的,导致JdbcUtil被加载了两次,丢失了第一次加载时初始化的值。
    结论: 删掉devtools依赖搞定,如果需要在启动监听中初始化值,就最好不要引用devtools,它自己实现了一个classloader,会导致你初始化的对象/值,因为后来类被AppClassLoader重新加载而丢失

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100
  • ¥15 关于#hadoop#的问题
  • ¥15 (标签-Python|关键词-socket)