You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity Android构建中iText DIContainer.GetInstance[T]空引用异常排查

问题:Unity Android构建中iText生成PDF抛出NullReferenceException

问题背景

使用iText在Unity中生成PDF,Windows编辑器运行正常,但Android构建版本抛出NullReferenceException,报错起始于iText.Commons.Utils.DIContainer.GetInstance[T]方法。已附上PDF生成代码(确认未输出pdfdocument日志)及用于防止代码裁剪的link.xml文件,怀疑link.xml存在问题,寻求解决办法。

异常信息

2026/06/01 12:45:41.669 29785 29810 Error Unity
NullReferenceException: Object reference not set to an instance of an object.
2026/06/01 12:45:41.669 29785 29810 Error Unity
at iText.Commons.Utils.DIContainer.GetInstance[T] () [0x00000] in <00000000000000000000000000000000>:0
2026/06/01 12:45:41.669 29785 29810 Error Unity
at iText.Kernel.Pdf.PdfPagesTree..ctor (iText.Kernel.Pdf.PdfCatalog pdfCatalog) [0x00000] in <00000000000000000000000000000000>:0
2026/06/01 12:45:41.669 29785 29810 Error Unity
at iText.Kernel.Pdf.PdfCatalog..ctor (iText.Kernel.Pdf.PdfDictionary pdfObject) [0x00000] in <00000000000000000000000000000000>:0
2026/06/01 12:45:41.669 29785 29810 Error Unity
at iText.Kernel.Pdf.PdfDocument.Open (iText.Kernel.Pdf.PdfVersion newPdfVersion) [0x00000] in <00000000000000000000000000000000>:0
2026/06/01 12:45:41.669 29785 29810 Error Unity
at iText.Kernel.Pdf.PdfDocument..ctor (iText.Kernel.Pdf.PdfWriter writer) [0x00000] in <00000000000000000000000000000000>:0
2026/06/01 12:45:41.669 29785 29810 Error Unity
at PdfGenerator.CreatePdfFromImages (System.Collections.Generic.List`1[T] imagePaths, System.String pdfFileName, System.String ouputPath) [0x00000] in <00000000000000000000000000000000>:0

PDF生成代码片段

Debug.Log("=====PDF GENERATION STARTED=====");

// 1. Initialize PDF writer and PDF document
PdfWriter writer = new PdfWriter(savePath);
Debug.Log("PDF Writer initialized at: " + savePath);
System.Runtime.CompilerServices.RuntimeHelpers
      .RunClassConstructor(typeof(iText.Commons.Utils.DIContainer).TypeHandle);
Debug.Log("DIContainer cctor forced");

PdfDocument pdfDoc = new PdfDocument(writer);
Debug.Log("PDF Document created successfully.");

// 2. Initialize layout Document (Defaults to A4)
Document document = new Document(pdfDoc, PageSize.A4);
Debug.Log("Layout Document initialized with A4 page size.");

// 2. Instantiate your custom handler
HeaderFooterHandler handler = new HeaderFooterHandler();
<linker>
    <!-- Force preservation of DIContainer AND its static constructor -->
    <assembly fullname="itext.commons" preserve="all">
        <type fullname="iText.Commons.Utils.DIContainer" preserve="all">
            <method signature="Void .cctor()" />
        </type>
        <type fullname="iText.Commons.Utils.DIContainerConfigurations" preserve="all">
            <method signature="Void .cctor()" />
            <method signature="Microsoft.Extensions.DependencyInjection.IServiceProvider Build()" />
            <method signature="Microsoft.Extensions.DependencyInjection.IServiceCollection Configure(Microsoft.Extensions.DependencyInjection.IServiceCollection)" />
        </type>
        <type fullname="iText.Commons.Actions.ProductProcessorFactoryKeeper" preserve="all">
            <method signature="Void .cctor()" />
        </type>
        <type fullname="iText.Commons.Actions.Processors.DefaultProductProcessorFactory" preserve="all">
            <method signature="Void .cctor()" />
        </type>
        <type fullname="iText.Commons.Bouncycastle.BouncyCastleFactoryCreator" preserve="all">
            <method signature="Void .cctor()" />
        </type>
    </assembly>

    <assembly fullname="itext.kernel" preserve="all">
        <type fullname="iText.Kernel.Pdf.PdfDocument" preserve="all">
            <method signature="Void .cctor()" />
        </type>
        <type fullname="iText.Kernel.Pdf.PdfPagesTree" preserve="all">
            <method signature="Void .cctor()" />
        </type>
    </assembly>

    <!-- Keep everything else the same as before -->
    <assembly fullname="itext" preserve="all"/>
    <assembly fullname="itext.io" preserve="all"/>
    <assembly fullname="itext.layout" preserve="all"/>
    <assembly fullname="itext.bouncy-castle-adapter" preserve="all"/>
    <assembly fullname="itext.bouncy-castle-fips-adapter" preserve="all"/>
    <assembly fullname="BouncyCastle.Cryptography" preserve="all"/>
    <assembly fullname="Microsoft.Extensions.DependencyInjection" preserve="all"/>
    <assembly fullname="Microsoft.Extensions.DependencyInjection.Abstractions" preserve="all"/>
    <assembly fullname="Microsoft.Extensions.Logging" preserve="all"/>
    <assembly fullname="Microsoft.Extensions.Logging.Abstractions" preserve="all"/>
    <assembly fullname="Microsoft.Extensions.Options" preserve="all"/>
    <assembly fullname="Microsoft.Extensions.Primitives" preserve="all"/>
    <assembly fullname="Microsoft.Bcl.AsyncInterfaces" preserve="all"/>
    <assembly fullname="System.Text.Json" preserve="all"/>
    <assembly fullname="System.Text.Encodings.Web" preserve="all"/>
    <assembly fullname="System.Runtime.Loader" preserve="all"/>
    <assembly fullname="System.Reflection.TypeExtensions" preserve="all"/>
</linker>

解决办法

空引用问题大概率是IL2CPP裁剪了DI容器依赖的服务实现类,更新link.xml补充关键类型的保留:

<linker>
    <assembly fullname="itext.commons" preserve="all">
        <type fullname="iText.Commons.Utils.DIContainer" preserve="all" />
        <type fullname="iText.Commons.Utils.DIContainerConfigurations" preserve="all" />
        <!-- 新增:保留DI容器需要的核心服务实现 -->
        <type fullname="iText.Commons.Utils.DefaultDIContainerConfiguration" preserve="all" />
        <type fullname="iText.Commons.Actions.DefaultProductEventHandler" preserve="all" />
        <type fullname="iText.Commons.Actions.Processors.DefaultProductProcessor" preserve="all" />
    </assembly>

    <assembly fullname="itext.kernel" preserve="all">
        <type fullname="iText.Kernel.Pdf.PdfDocument" preserve="all" />
        <type fullname="iText.Kernel.Pdf.PdfPagesTree" preserve="all" />
        <type fullname="iText.Kernel.Pdf.PdfCatalog" preserve="all" />
    </assembly>

    <!-- 保留其他必要程序集 -->
    <assembly fullname="itext" preserve="all"/>
    <assembly fullname="itext.io" preserve="all"/>
    <assembly fullname="itext.layout" preserve="all"/>
    <assembly fullname="itext.bouncy-castle-adapter" preserve="all"/>
    <assembly fullname="BouncyCastle.Cryptography" preserve="all"/>
    <assembly fullname="Microsoft.Extensions.DependencyInjection" preserve="all"/>
    <assembly fullname="Microsoft.Extensions.DependencyInjection.Abstractions" preserve="all"/>
</linker>

2. 强制完整初始化DI容器链

在代码中提前触发所有相关类型的静态构造,并初始化DI容器实例,避免延迟加载导致的空引用:

Debug.Log("=====PDF GENERATION STARTED=====");

// 强制初始化所有DI相关类型的静态构造函数
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(iText.Commons.Utils.DIContainer).TypeHandle);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(iText.Commons.Utils.DIContainerConfigurations).TypeHandle);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(iText.Commons.Utils.DefaultDIContainerConfiguration).TypeHandle);

// 提前获取DI实例,确保容器完全初始化
var tempHandler = iText.Commons.Utils.DIContainer.GetInstance<iText.Commons.Actions.IProductEventHandler>();
Debug.Log("DI container initialized: " + tempHandler);

// 再初始化PDF相关对象
PdfWriter writer = new PdfWriter(savePath);
Debug.Log("PDF Writer initialized at: " + savePath);

PdfDocument pdfDoc = new PdfDocument(writer);
Debug.Log("PDF Document created successfully.");

// 后续代码...

3. 调整Unity IL2CPP构建设置

  • 在Player Settings中,将IL2CPP Code Generation设置为Faster Runtime,减少激进的代码裁剪;
  • 开启Development Build并勾选Script Debugging,获取更详细的错误堆栈,排查是否有其他被裁剪的类型。

4. 验证iText版本兼容性

确保使用iText 7.2.x及以上版本,该版本对.NET Standard支持更完善,能更好适配Unity的Android构建环境。

内容的提问来源于stack exchange,提问作者Muhammad Faizan Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.02 11:38:08