版本:23.8
编程语言:java
现象:
在客户的阿里云云服务器(windows操作系统),
执行以下代码时(Document doc = new Document(new ByteArrayInputStream(bytes));),进程卡死
异常文件:
龙华站合同终止_通知函_20251125 补充非电 -1126 Clean.docx (37.7 KB)
jstack命令输出结果:
版本:23.8
编程语言:java
现象:
在客户的阿里云云服务器(windows操作系统),
执行以下代码时(Document doc = new Document(new ByteArrayInputStream(bytes));),进程卡死
异常文件:
龙华站合同终止_通知函_20251125 补充非电 -1126 Clean.docx (37.7 KB)
jstack命令输出结果:
感谢您使用 Aspose.Words for Java。
针对您在阿里云 Windows 服务器上执行
Document doc = new Document(new ByteArrayInputStream(bytes));
时出现 卡死(进程不返回)的情况,下面提供几个常见的排查思路以及对应的解决方案。
Aspose.Words 在解析 Word 文档时会尝试加载系统中可用的字体。
如果服务器上缺少常用的中文/西文字体(尤其是 SimSun、SimHei、Arial、Times New Roman 等),在某些包含复杂字体设置的 DOCX 中会触发内部的字体解析循环,从而导致卡死。
解决办法
安装常规字体
在 Windows Server 上打开 “控制面板 → 字体”,确保已安装以下字体(至少):
SimSun(宋体)
SimHei(黑体)
Microsoft YaHei(微软雅黑)
Arial
Times New Roman
使用自定义 FontSettings(不依赖系统字体):
// 1) 创建 FontSettings 并指向本地字体文件夹
FontSettings fontSettings = new FontSettings();
fontSettings.setFontsFolder("C:/MyFonts", true); // 将所有需要的 TTF/OTF 放到此文件夹
// 2) 将 FontSettings 注入到 LoadOptions
LoadOptions loadOptions = new LoadOptions();
loadOptions.setFontSettings(fontSettings);
// 3) 用 LoadOptions 加载文档
Document doc = new Document(new ByteArrayInputStream(bytes), loadOptions);
建议:先在本机(已装完整字体)运行一次代码,确认能够正常加载文档。如果本机可以,但服务器卡死,则几乎可以确认是字体缺失导致。
您当前使用的是 23.8,该版本在处理某些特殊结构的 DOCX(尤其是嵌入的 VML/SmartArt、图表或宏)时曾报告过死锁问题。
官方已在 24.3 及以后版本中修复相关 bug。
升级步骤
修改 Maven/Gradle/手动 jar 引用,更新为最新稳定版(截至本文撰写时为 24.6):
<!-- Maven 示例 -->
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>24.6</version>
</dependency>
重新编译并部署到服务器。
LoadOptions 明确指定加载格式有时文件扩展名与内部标记不匹配,Aspose 需要额外的检测时间。将加载格式显式指定为 DOCX 能够避免内部格式探测的额外开销。
LoadOptions loadOptions = new LoadOptions(LoadFormat.DOCX);
Document doc = new Document(new ByteArrayInputStream(bytes), loadOptions);
如果仍然卡死,可通过以下方式获取更详细的日志:
开启 Aspose.Words 调试日志(从 24.x 起支持):
System.setProperty("aspose.words.debug", "true");
System.setProperty("aspose.words.log", "aspose-words-debug.log");
使用 jstack 捕获完整线程堆栈(您已提供部分截图)。请重点查看 com.aspose.words.Document 构造函数内部的等待或锁定情况。若看到大量 java.lang.Object.wait(),通常是因为字体加载阻塞。
将完整的 jstack 输出(文本形式)贴回贴子,便于我们进一步定位。
您提供的 龙华站合同终止_通知函_20251125 补充非电 -1126 Clean.docx 大小仅 37.7 KB,属于小文件,但可能含有 嵌入的 VML 图形、SmartArt、宏 或 损坏的关系文件。可以尝试以下操作验证:
| 方法 | 操作步骤 |
|---|---|
| OpenXML SDK 检查 | 使用 System.IO.Packaging.ZipPackage 打开文档,检查 word/_rels/document.xml.rels 中是否有指向不存在的目标。 |
| Word 官方修复 | 在本地装有 Office 的机器上打开文档 → “文件 → 打开并修复”,然后保存为 docx,再上传服务器测试。 |
| 先转为 PDF 再回读 | 使用 Aspose.Words 将文档先转为 PDF(doc.save("tmp.pdf")),确认 PDF 能够生成。如果 PDF 正常,则说明文档读取本身没问题,卡死可能是 PDF 转换 环节的其它设置。 |
import com.aspose.words.*;
import java.io.ByteArrayInputStream;
public class DocxToPdf {
public static void main(String[] args) throws Exception {
// 1) 读取文件字节(这里假设已经读取到 byte[] bytes)
byte[] bytes = java.nio.file.Files.readAllBytes(
java.nio.file.Paths.get("C:/temp/input.docx"));
// 2) 配置字体(若服务器缺少系统字体)
FontSettings fontSettings = new FontSettings();
fontSettings.setFontsFolder("C:/MyFonts", true); // 放入必需的中文字体
// 3) 使用 LoadOptions 明确指定 DOCX 格式并注入 FontSettings
LoadOptions loadOptions = new LoadOptions(LoadFormat.DOCX);
loadOptions.setFontSettings(fontSettings);
// 4) 加载文档
Document doc = new Document(new ByteArrayInputStream(bytes), loadOptions);
// 5) 保存为 PDF(可根据需要设置 PDF 保存选项)
PdfSaveOptions pdfOptions = new PdfSaveOptions();
pdfOptions.setSaveFormat(SaveFormat.PDF);
doc.save("C:/temp/output.pdf", pdfOptions);
System.out.println("转换完成。");
}
}
FontSettings)。LoadOptions 明确指定加载格式,并重新测试。期待您的反馈,祝您使用顺利!
链接汇总
如果还有其他细节(如完整堆栈、日志文件)请随时补充,我们会继续协助您定位根本原因。
@ZhonghaoSun 问题似乎在于多个线程同时尝试初始化类,导致并行类加载时发生死锁。具体表现为多个线程首次同时使用Aspose.Words时,会触发并行类加载导致死锁。建议提前同步初始化Aspose.Words。