简要记录在Linux(Ubuntu)操作系统上发布AOT程序时,发现System.Text.Json组件在Json序列化时抛出异常的处理步骤。
在 .NET 6 及更高版本中,可以使用 Ahead-of-Time (AOT) 编译来优化应用程序的启动时间和性能。AOT 编译通过 .NET Native AOT 实现,适用于需要快速启动和小型部署的场景。要使用 AOT 编译,需要在项目文件中进行配置,并使用命令行工具进行发布。以下是一个配置和发布 AOT 的简单步骤示例:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net9.0</TargetFramework> <PublishAot>true</PublishAot> </PropertyGroup> </Project>
发布命令:
dotnet publish -c Release -r linux-x64 --self-contained
问题1,不同操作系统:如果你是首次发布,可能会遇到以下问题:
error : Cross-OS native compilation is not supported.
该错误消息表明你正在尝试在与目标操作系统不同的环境中进行原生编译(AOT)。简单来说,你可能是在 Windows 或 macOS 上尝试为 Linux 进行 AOT 编译,而这种跨操作系统的编译是不被支持的。因此,最简单的解决办法是将代码复制到 Ubuntu 然后再进行编译。
问题2,缺少环境:当我们将代码复制到 Ubuntu 操作系统上后,再次执行发布命令进行编译(可以使用 VS Code 或 Rider)时,会遇到以下问题:
/home/justerzhu/.nuget/packages/microsoft.dotnet.ilcompiler/8.0.10/build/Microsoft.NETCore.Native.Unix.targets(209,5): error : Platform linker ('clang' or 'gcc') not found in PATH. Ensure you have all the required prerequisites documented at https://aka.ms/nativeaot-prerequisites. [/home/justerzhu/Documents/code/client/GeneralUpdate.Client/GeneralUpdate.Client.csproj]
该错误消息表明在你的 Linux 环境中没有找到平台链接器(clang 或 gcc)。在使用 .NET 的 AOT 编译时,需要使用这些工具来处理本机代码的链接。解决这个问题的步骤如下:
安装必要的工具:你需要确保在 Linux 系统上安装了 clang 或 gcc。以下是如何在常见的 Linux 发行版上安装这些工具的步骤:
Ubuntu 更新软件包列表:
sudo apt update
安装 clang 和 gcc:
sudo apt install clang gcc
确保 clang 或 gcc 在你的 PATH 中:
安装完成后,通常它们会自动添加到 PATH 中。可以通过以下命令检查:
clang --version gcc --version
如果这些命令返回版本信息,则说明安装成功。
检查链接器:确保你的环境能够正确找到链接器。在终端中运行以下命令以确认:
which clang which gcc
如果这两个命令中的任意一个返回路径,则说明链接器已正确安装并在 PATH 中。
问题3,缺少环境的问题再次来袭:当我们满怀信心再次执行发布命令时,突然又出现了问题:
error : linker command failed with exit code 1 (use -v to see invocation) [/home/justerzhu/Documents/code/client/GeneralUpdate.Client/GeneralUpdate.Client.csproj] /home/justerzhu/.nuget/packages/microsoft.dotnet.ilcompiler/8.0.10/build/Microsoft.NETCore.Native.targets(366,5): error MSB3073: The command ""clang" "obj/Release/net8.0/linux-x64/native/GeneralUpdate.Client.o" -o "bin/Release/net8.0/linux-x64/native/GeneralUpdate.Client" -Wl,--version-script=obj/Release/net8.0/linux-x64/native/GeneralUpdate.Client.exports -Wl,--export-dynamic -gz=zlib -fuse-ld=bfd /home/justerzhu/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/8.0.10/sdk/libbootstrapper.o /home/justerzhu/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/8.0.10/sdk/libRuntime.WorkstationGC.a /home/justerzhu/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/8.0.10/sdk/libeventpipe-disabled.a /home/justerzhu/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/8.0.10/sdk/libstdc++compat.a /home/justerzhu/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/8.0.10/framework/libSystem.Native.a /home/justerzhu/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/8.0.10/framework/libSystem.Globalization.Native.a /home/justerzhu/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/8.0.10/framework/libSystem.IO.Compression.Native.a /home/justerzhu/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/8.0.10/framework/libSystem.Net.Security.Native.a /home/justerzhu/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/8.0.10/framework/libSystem.Security.Cryptography.Native.OpenSsl.a -g -Wl,-rpath,'$ORIGIN' -Wl,--build-id=sha1 -Wl,--as-needed -pthread -ldl -lz -lrt -lm -pie -Wl,-pie -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,--discard-all -Wl,--gc-sections" exited with code 1. [/home/justerzhu/Documents/code/client/GeneralUpdate.Client/GeneralUpdate.Client.csproj]
该错误表明在链接阶段出现了问题,导致 clang 链接器命令失败并返回了非零退出代码。要解决这个问题,我们需要进一步分析错误原因。以下是一些可能的原因和解决方案:
检查依赖库:缺少依赖库:
确保你已经安装了所有必需的开发库。特别是对于 Linux 上的 AOT 编译,可能需要一些额外的库,例如 libc-dev、libz-dev、libssl-dev 等。你可以通过以下命令安装常用的开发库:
sudo apt install build-essential zlib1g-dev libssl-dev
链接器选项问题:
有时错误可能是由于链接器选项不兼容或不正确。检查项目文件或构建配置中是否有自定义的链接器选项,确保它们是正确的。
增加详细输出:增加编译过程的详细输出可以帮助你了解问题的细节:
dotnet publish -c Release -r linux-x64 --self-contained -v diag
-v diag 会输出详细的诊断信息,可以帮助你找到更具体的错误原因。
检查代码中使用的库:如果你的项目中使用了某些特定的 C++ 或本地库,确保它们的头文件和库文件在 Linux 环境中是可用且兼容的。
验证 Native AOT 的支持:确认使用的 .NET Native AOT 工具链版本是正确的,并且你的项目和依赖项支持 AOT 编译。某些第三方库或特性可能不支持 AOT 编译。
使用最新的工具链:确保使用的是最新版本的 .NET SDK 和工具链。你可以通过以下命令更新你的 .NET SDK:
sudo apt update sudo apt install dotnet-sdk-8.0
问题4,版本不一致:在 Linux 发布之前我安装了 .NET 8 的运行环境,但是我项目里应用的是 .NET 9 的 NuGet,这时候就导致了无法正常发布 AOT。所以这里也是提醒各位发布之前注意版本对齐。
System.MissingMethodException: Method not found: 'Void System.Text.Json.Serialization.Metadata.JsonObjectInfoValues1<generalupdate.common.shared.object.versionrespdto>.set_ConstructorAttributeProviderFactory(System.Func1<system.reflection.icustomattributeprovider>)'.at Internal.Runtime.TypeLoaderExceptionHelper.CreateMissingMethodException(ExceptionStringID, String) + 0x47at Internal.Runtime.CompilerHelpers.ThrowHelpers.ThrowMissingMethodException(ExceptionStringID, String) + 0x6at GeneralUpdate.Common.AOT.JsonContext.VersionRespJsonContext.Create_VersionRespDTO(JsonSerializerOptions) + 0x12at System.Text.Json.JsonSerializerOptions.GetTypeInfoNoCaching(Type) + 0x43at System.Text.Json.JsonSerializerOptions.CachingContext.CreateCacheEntry(Type type, JsonSerializerOptions.CachingContext context) + 0x1e--- End of stack trace from previous location ---at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x1cat System.Text.Json.JsonSerializerOptions.CachingContext.CacheEntry.GetResult() + 0x1bat System.Text.Json.JsonSerializerOptions.GetTypeInfoInternal(Type, Boolean, Nullable`1, Boolean, Boolean) + 0x44at System.Text.Json.JsonSerializerOptions.GetTypeInfo(Type) + 0x49at GeneralUpdate.Common.AOT.JsonContext.VersionRespJsonContext.get_VersionRespDTO() + 0x39at GeneralUpdate.Common.Shared.Service.VersionService.<validate>d__2.MoveNext() + 0x114--- End of stack trace from previous location ---at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() + 0x1cat System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task) + 0xbeat System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task, ConfigureAwaitOptions) + 0x4eat GeneralUpdate.ClientCore.GeneralClientBootstrap.<executeworkflowasync>d__13.MoveNext() + 0x109</executeworkflowasync></validate></system.reflection.icustomattributeprovider></generalupdate.common.shared.object.versionrespdto>
这个时候只能在电脑上把 NuGet 的版本一个个对齐或者安装对应 .NET 的版本即可。
问题5,Json序列化怎么转都报错:具体的报错我没有记录,但是不处理 Json 序列化一定会报错。下面这段代码在非 AOT 发布的情况下是可以正常使用的,但在 AOT 发布时存在问题(原因在参考资料中了解)。
var jsonStr = JsonSerializer.Serialize(parameters);
参考资料:
https://www.php.cn/link/ba9d98e8e54041173ea4f3640ed79cachttps://www.php.cn/link/26c7cc8d05a0dc19cfc07baa975877f1
这时候只能找找参考资料,看完一遍之后大致写法如下:
class Packet { [JsonPropertyName("Name")] public string? Name { get; set; } [JsonPropertyName("Hash")] public string Hash { get; set; } <pre class="brush:php;toolbar:false">//....
}
[JsonSerializable(typeof(Packet))] public partial class PacketJsonContext : JsonSerializerContext;
var jsonStr = JsonSerializer.Serialize(parameters, PacketJsonContext.Default.Packet);
以上就是.NET9 Linux AOT Json序列化的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号