WxJava icon indicating copy to clipboard operation
WxJava copied to clipboard

企业微信会话存档下载时总是时不时出现报错,导致整个JVM直接崩溃

Open yiming33 opened this issue 5 months ago • 2 comments

简要描述

企业微信会话存档下载时总是时不时出现报错,导致整个JVM直接崩溃

模块版本情况

  • WxJava 模块名: weixin-java-cp
  • WxJava 版本号: 4.7.5-20250516.201941

详细描述

public List<WeworkMessage> pullWeworkChatData(long seq, long limit, Predicate<String> duplicateMessageFilter) throws Exception {

    // 本次请求获取消息记录开始的seq值。首次访问填写0,非首次使用上次企业微信返回的最大seq。允许从任意seq重入拉取。
    WxCpChatDatas chatDatas = wxCpService.getMsgAuditService().getChatDatas(seq, limit, null, null, 1000L);
    if (chatDatas == null || CollUtil.isEmpty(chatDatas.getChatData())) {
        log.info("未读取到数据,当前序列为: {}", seq);
        return Collections.emptyList();
    }

    List<WeworkMessage> weworkMessages = new ArrayList<>();
    for (WxCpChatDatas.WxCpChatData chatData : chatDatas.getChatData()) {
        seq = chatData.getSeq();

        // 过滤掉重复消息,判断是否重复,如果重复则跳过
        if (duplicateMessageFilter.test(chatData.getMsgId())) {
            WeworkMessage weworkMessage = new WeworkMessage();
            weworkMessage.setExists(true);
            weworkMessage.setMsgId(chatData.getMsgId());
            weworkMessage.setMsgSeq(chatData.getSeq());
            weworkMessages.add(weworkMessage);
            continue;
        }
        // 获取明文数据
        final String chatPlainText = wxCpService.getMsgAuditService().getChatPlainText(chatDatas.getSdk(), chatData, 2);
        final WxCpChatModel decryptData = WxCpChatModel.fromJson(chatPlainText);
        log.info("当前数据序列为:{},明文数据为:{}", seq, decryptData.toJson());

        WorkMessageType msgType = WorkMessageType.fromType(decryptData.getMsgType());
        if (msgType == null) {
            log.info("不支持的消息类型:{}", decryptData.getMsgType());
            continue;
        }

        WeworkMessage weworkMessage = new WeworkMessage();
        weworkMessages.add(weworkMessage);

        weworkMessage.setMsgType(msgType);
        weworkMessage.setMsgSeq(chatData.getSeq());
        weworkMessage.setMessageInfo(decryptData);
        weworkMessage.setMsgId(decryptData.getMsgId());


        if (!MEDIA_MESSAGE_TYPES.contains(decryptData.getMsgType())) {
            break;
        }

        try {
            WeworkMessage.Media media = downloadMediaFile(decryptData.getMsgType(), decryptData, weworkProperties.getTmpFileDirPath(), chatDatas);
            weworkMessage.setMediaInfo(media);
        } catch (WxErrorException e) {
            log.error("下载文件失败", e);
        }

        if (StrUtil.isNotBlank(decryptData.getRoomId())) {
            var groupChat = groupChatMap.get(decryptData.getRoomId());
            if (groupChat == null) {
                try {
                    groupChat = wxCpService.getMsgAuditService().getGroupChat(decryptData.getRoomId());
                    groupChatMap.put(decryptData.getRoomId(), groupChat);
                } catch (WxErrorException e) {
                    log.error("无法获取外部群,跳过本次群信息获取");
                }

            }

            weworkMessage.setGroupInfo(groupChat);
        }


    }


    // 批次数据拉取完毕后,释放此次sdk
    log.info("释放sdk {}", chatDatas.getSdk());
    Finance.DestroySdk(chatDatas.getSdk());
    return weworkMessages;
}

/**
 * 获取媒体文件,
 * 不同的文件类型,拼接好存放文件的绝对路径,写入文件流,获取媒体文件。
 * <p>
 * 目标文件绝对路径+实际文件名,比如:/tmp/workpulse/file/20220114/474f866b39d10718810d55262af82662.gif
 */
private WeworkMessage.Media downloadMediaFile(String msgType, WxCpChatModel decryptData, String path, WxCpChatDatas chatDatas) throws WxErrorException {
    // 文件后缀
    String suffix = "";
    // 文件名md5
    String md5Sum = "";
    String fileName = "";
    // sdkFileId
    String sdkFileId = "";
    switch (msgType) {
        case WxCpConsts.MsgAuditMediaType.IMAGE:
            suffix = WxCpConsts.MsgAuditMediaType.MsgAuditSuffix.JPG;
            md5Sum = decryptData.getImage().getMd5Sum();
            sdkFileId = decryptData.getImage().getSdkFileId();
            break;
        case WxCpConsts.MsgAuditMediaType.VOICE:
            suffix = WxCpConsts.MsgAuditMediaType.MsgAuditSuffix.AMR;
            md5Sum = decryptData.getVoice().getMd5Sum();
            sdkFileId = decryptData.getVoice().getSdkFileId();
            break;
        case WxCpConsts.MsgAuditMediaType.VIDEO:
            suffix = WxCpConsts.MsgAuditMediaType.MsgAuditSuffix.MP4;
            md5Sum = decryptData.getVideo().getMd5Sum();
            sdkFileId = decryptData.getVideo().getSdkFileId();
            break;
        case WxCpConsts.MsgAuditMediaType.FILE:
            md5Sum = decryptData.getFile().getMd5Sum();
            suffix = "." + decryptData.getFile().getFileExt();
            fileName = decryptData.getFile().getFileName();
            sdkFileId = decryptData.getFile().getSdkFileId();
            break;
        default:
            break;
    }

    // 拉取媒体文件
    String finalFileName = StringUtils.isBlank(fileName) ? md5Sum + suffix : fileName;
    String targetPath = path + UUID.randomUUID().toString().replaceAll("-", "") + "/" + finalFileName;
    log.info("获取到媒体文件:{}", targetPath);
    wxCpService.getMsgAuditService().getMediaFile(chatDatas.getSdk(), sdkFileId, null, null, 1000L, targetPath);

    return new WeworkMessage.Media(md5Sum, suffix, fileName, sdkFileId, targetPath);
}

日志

如果日志不多,直接使用md代码引用格式贴在此处,否则如果太长,请将日志放在 pastebin 或者其他地方,然后将其url地址贴在这里

日志请写于此处

这个出现的频率很高,某一条消息同步的时候,如果无法同步下来,无论重新尝试多少次都会导致JVM崩溃 错误信息: : 获取到媒体文件:tmp/file/4ab074d5ce5d49f7ad4910741cb95301/eac71674ab4fcf8a979af377b8ea3b92.jpg

A fatal error has been detected by the Java Runtime Environment:

SIGSEGV (0xb) at pc=0x00007fcd50460d93, pid=2614462, tid=2614831

JRE version: Java(TM) SE Runtime Environment (17.0.14+8) (build 17.0.14+8-LTS-191)

Java VM: Java HotSpot(TM) 64-Bit Server VM (17.0.14+8-LTS-191, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)

Problematic frame:

C [libWeWorkFinanceSdk_Java.so+0x260d93] WeWorkFinanceSdk::TryRefresh(std::string const&, std::string const&, int)+0x23

Core dump will be written. Default location: Core dumps may be processed with "/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h %e" (or dumping to /home/jsol_ops/app/jsol/workpulse/wework/dev/core.2614462)

An error report file with more information is saved as:

/home/jsol_ops/app/jsol/workpulse/wework/dev/hs_err_pid2614462.log

If you would like to submit a bug report, please visit:

https://bugreport.java.com/bugreport/crash.jsp

The crash happened outside the Java Virtual Machine in native code.

See problematic frame for where to report the bug.

yiming33 avatar Aug 06 '25 14:08 yiming33

仔细查看下代码调用顺序,应该是调用顺序有问题。downloadMediaFile下载文件时需要异步,媒体文件是分批拉取的,需要异步拉取

0katekate0 avatar Aug 13 '25 08:08 0katekate0

@yiming33 ,兄弟,解决没,我也遇到这问题了,但是我不确定是什么导致崩溃的,但是可以肯定是会话存档这个

ideaviewes avatar Oct 24 '25 10:10 ideaviewes

WeWorkFinanceSdk::TryRefresh 这个 怎么处理的老板

58213 avatar Nov 18 '25 09:11 58213