Unity Android构建中iText DIContainer.GetInstance[T]空引用异常排查
问题背景
使用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();
link.xml文件内容
<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>
解决办法
1. 修正link.xml的类型保留规则
空引用问题大概率是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

