前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Intellij运行Java程序启动等待BUG分享

Intellij运行Java程序启动等待BUG分享

作者头像
FunTester
发布2021-06-23 10:36:28
5330
发布2021-06-23 10:36:28
举报
文章被收录于专栏:FunTesterFunTester

最近公司新配了一台Mac本,性能相比之前自己的Mac本提升了很多,在配置基础运行环境之后,我运行了一下自己的项目,发现了一个巨大的问题。

我居然无意中触发了一个JDKBUG

现象

打包编译代码非常快,但是在使用其他功能,甚至只是引入log4j2日志功能之后,会显得启动非常慢,通常能达到好几秒才能在控制台看到输出信息,这一点极不寻常。

PS:不是log4j2的问题,当时把终点怀疑对象放在了log4j2上了。

排查

我一开始以为是自己导入旧电脑的配置到底的,后来发现不是。中间怀疑过很多方面,甚至系统我都升级了一下,也没有解决问题。在经历了各种JVM调优文章的洗礼之后,我也开始放弃了这条思路。转而往我不懂的领域搜索答案了。

按照网上大佬的排查流程,我走了一遍,发现在启动之前我做了一些事情,有一些配置的初始化程序,如下:

代码语言:javascript
复制
 /**
     * 创建日志文件夹和数据存储文件夹
     */
    static {
        new File(LOG_Path).mkdir();
        new File(LONG_Path).mkdir();
        File file = new File(REQUEST_Path);
        File mark = new File(MARK_Path);
        File data = new File(DATA_Path);
        file.mkdir();
        mark.mkdir();
        data.mkdir();
        List<String> allFile = FileUtil.getAllFile(DATA_Path);
        allFile.addAll(FileUtil.getAllFile(MARK_Path));
        allFile.addAll(FileUtil.getAllFile(REQUEST_Path));
        allFile.stream().map(y -> new File(y)).forEach(x -> {
            if (Time.getTimeStamp() - x.lastModified() > 3 * DAY) x.delete();
        });
        logger.info("当前用户:{},IP:{},工作目录:{},系统编码格式:{},系统{}版本:{}", COMPUTER_USER_NAME, LOCAL_IP, WORK_SPACE, SYS_ENCODING, SYS_NAME, SYS_VERSION);
    }

这里比较重要的一点就是LOCAL_IP,在获取LOCAL_IP的方法中,我是这么写的:

代码语言:javascript
复制
    /**
     * 获取本机IP
     *
     * @return
     */
    public static String getLocalIp() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            logger.warn("获取本机IP失败!", e);
            return EMPTY;
        }
    }

这是一个非常简单的方法,我居然发现这个地方居然执行了5s,然后我把改代码注释掉了,相关的功能暂时也关闭了。

可问题依然存在,除了System.out.println(“FunTester”);代码以外,其他添加任何功能都会带来启动时间的猛增,即使我只增加了日志打印功能。

真相大白

在常规方法失效以后,我只能去stackoverflow求助了。申请的事情就这么发生了,原来早就有不少人遇到这个问题,不过看起来他们比较严重,据资料显示有等待30s甚至60s之久的。

下面是某个提问者所做的排查工作:

代码语言:javascript
复制
我在系统上更改了JDK。
我更改了IntelliJ版本。
我改为IntelliJ Ultimate-试用版。
使IDE的缓存无效。
我还发现给定的消息仅在代码的这一部分存在-github -project,所以我更改了JVM选项以给InteliJ更多内存。

然后底下大佬们给出了答案,具体解释如下:

代码语言:javascript
复制
IntelliJ支持反馈:问题是java.net.Inet4AddressImpl.getLocalHostName(Native Method)JDK方法调用中存在挂起的问题,该问题导致获得系统主机名。这是JDK问题或本地配置问题...

据资料显示,这个应该在2017年就已经出现了,用英文搜索,其实很容易得到答案的。

具体的解释如下,这是一个JDKBUG,不错,这就是一个openJDKBUG

代码语言:javascript
复制
要重现该问题的步骤:
1.将Mac连接到IPv6 DNS断开的网络(抱歉,我不知道网络配置的详细信息)
2.通过导出JAVA_TOOL_OPTIONS = -Djava.net.preferIPv4Stack = true强制Java使用IPv4。
3.运行测试用例,打印出java.net.InetAddress.getLocalHost()的结果


预期的实际行为:
预期的 -
返回的本地主机地址(以毫秒为单位)
实际的 -
延迟5秒后返回本地主机地址

由于Java程序获取本机地址的时候出现错误,导致5s等待(这个应该是默认超时时间),然后再加上重试机制,所以报告的等待时间基本都是5s的整数倍。

修复方案

方案1:

添加下面内容到/etc/hosts文件中

代码语言:javascript
复制
127.0.0.1       localhost       <your hostname>.local
::1             localhost       <your hostname>.local

方案2:

通过设置别名实现

sudo ifconfig en0 alias 127.0.0.1 alias 127.0.0.1

方案3:

升级JDK版本,目前搜到的资料上,问题出现在78的部分版本(尚不确定)。理论上可以通过补丁解决,也有人开发了,谨慎起见,这个方案可以往后排。

  • 我采取了方案1,已经完美解决了这个问题。

附上一张我的网络IPv6测试图:

IPv6测试图

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-03-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FunTester 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 现象
  • 排查
  • 真相大白
  • 修复方案
相关产品与服务
数据保险箱
数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档