编译MATLAB应用使用NCTOOLBOX出现No such method错误求助
问题背景
我需要在编译后的MATLAB应用中使用NCTOOLBOX。未编译状态下代码能正常调用该工具箱,但编译后执行相同任务时,脚本无法找到正确的Java驱动。
我熟悉MATLAB应用编译流程,同一应用中已成功集成其他Java驱动,方法是在Application Compiler的「传递给mcc的附加参数」中添加.jar文件,示例:
-a "C:\someFilePath\postgresql-42.2.12.jar"
未编译时则通过以下方式加载驱动,运行正常:
javaaddpath('C:\someFilePath\postgresql-42.2.12.jar');
报错详情
报错出现在NCTOOLBOX的ncdataset.m文件第87行,代码为:
obj.netcdf = ucar.nc2.dataset.NetcdfDataset.openDataset(url)
完整错误信息:
Error using ncdataset (line 87)
Java exception occurred:
java.io.IOException: java.lang.RuntimeException: java.lang.NoSuchMethodError: ucar.nc2.grib.grib2.Grib2IndexProto$GribIdSection.emptyIntList()Lcom/google/protobuf/Internal$IntList;
at ucar.nc2.NetcdfFile.open(NetcdfFile.java:401)
at ucar.nc2.dataset.NetcdfDataset.openProtocolOrFile(NetcdfDataset.java:831)
at ucar.nc2.dataset.NetcdfDataset.openDataset(NetcdfDataset.java:479)
at ucar.nc2.dataset.NetcdfDataset.openDataset(NetcdfDataset.java:461)
at ucar.nc2.dataset.NetcdfDataset.openDataset(NetcdfDataset.java:442)
at ucar.nc2.dataset.NetcdfDataset.openDataset(NetcdfDataset.java:426)
Caused by: java.lang.RuntimeException: java.lang.NoSuchMethodError: ucar.nc2.grib.grib2.Grib2IndexProto$GribIdSection.emptyIntList()Lcom/google/protobuf/Internal$IntList;
at ucar.nc2.NetcdfFile.(NetcdfFile.java:1634)
at ucar.nc2.NetcdfFile.open(NetcdfFile.java:798)
at ucar.nc2.NetcdfFile.open(NetcdfFile.java:398)
... 5 more
Caused by: java.lang.NoSuchMethodError: ucar.nc2.grib.grib2.Grib2IndexProto$GribIdSection.emptyIntList()Lcom/google/protobuf/Internal$IntList;
at ucar.nc2.grib.grib2.Grib2IndexProto$GribIdSection.(Grib2IndexProto.java:140)
at ucar.nc2.grib.grib2.Grib2IndexProto$GribIdSection.(Grib2IndexProto.java:1395)
at ucar.nc2.grib.grib2.Grib2Index.makeIdProto(Grib2Index.java:334)
at ucar.nc2.grib.grib2.Grib2Index.makeRecordProto(Grib2Index.java:286)
at ucar.nc2.grib.grib2.Grib2Index.makeIndex(Grib2Index.java:243)
at ucar.nc2.grib.GribIndex.readOrCreateIndexFromSingleFile(GribIndex.java:94)
at ucar.nc2.grib.collection.Grib2CollectionBuilder.makeGroups(Grib2CollectionBuilder.java:84)
at ucar.nc2.grib.collection.GribCollectionBuilder.createMultipleRuntimeCollections(GribCollectionBuilder.java:128)
at ucar.nc2.grib.collection.GribCollectionBuilder.createIndex(GribCollectionBuilder.java:120)
at ucar.nc2.grib.collection.GribCdmIndex.openGribCollectionFromDataFile(GribCdmIndex.java:825)
at ucar.nc2.grib.collection.GribCdmIndex.openGribCollectionFromDataFile(GribCdmIndex.java:804)
at ucar.nc2.grib.collection.GribCdmIndex.openGribCollectionFromRaf(GribCdmIndex.java:774)
at ucar.nc2.grib.collection.GribIosp.open(GribIosp.java:201)
at ucar.nc2.NetcdfFile.(NetcdfFile.java:1610)
... 7 moreError in cfdataset (line 59) Error in ncgeodataset (line 74)
我已经尝试添加NCTOOLBOX附带的所有.jar文件,但问题依旧。另外注意到NCTOOLBOX的ncugrid.m中有一段导入ucar相关类的代码块,不确定是否需要在编译配置中做特殊设置来替代这个import块:
import ucar.ma2.Array; import ucar.ma2.DataType; import ucar.nc2.Attribute; import ucar.nc2.Dimension; import ucar.nc2.Variable; import ucar.nc2.dataset.CoordinateSystem; import ucar.nc2.dataset.NetcdfDataset; import ucar.nc2.dataset.VariableDS; import ucar.nc2.dt.ugrid.Cell; import ucar.nc2.dt.ugrid.Edge; import ucar.nc2.dt.ugrid.Face; import ucar.nc2.dt.ugrid.Node; import ucar.nc2.dt.ugrid.UGridDataset; import ucar.nc2.dt.ugrid.geom.LatLonPoint2D;
解决思路与方案
1. 检查Protobuf依赖版本冲突
错误提示NoSuchMethodError指向Google Protobuf的方法,说明编译后的应用中存在Protobuf版本不匹配的问题:
- 确认NCTOOLBOX依赖的Protobuf版本,检查是否与MATLAB自带的Protobuf版本冲突(MATLAB可能自带了旧版Protobuf)
- 在编译参数中显式指定NCTOOLBOX配套的Protobuf.jar文件,确保优先级高于MATLAB自带版本,比如:
-a "C:\path\to\nctoolbox\lib\protobuf-java-x.x.x.jar"
2. 确保所有NCTOOLBOX依赖的Jar文件完整添加
不要只添加NCTOOLBOX根目录下的Jar,需要检查其lib子目录中所有依赖Jar,比如:
cdm-x.x.x.jargrib-x.x.x.jarprotobuf-java-x.x.x.jar- 其他第三方依赖Jar
将所有这些Jar通过-a参数添加到编译配置中,确保没有遗漏。
3. 调整Java类路径加载顺序
在MATLAB代码中,编译前通过javaclasspath命令查看当前类路径顺序,确保NCTOOLBOX的Jar优先级高于MATLAB自带的冲突Jar。编译时可以通过-J-Djava.class.path=参数强制指定类路径,例如:
-J-Djava.class.path="C:\path\to\nctoolbox\lib\*;%CLASSPATH%"
注意使用*通配符加载目录下所有Jar,同时保留系统原类路径。
4. 关于import块的处理
MATLAB的import语句只是语法糖,编译时会自动解析对应的Java类,不需要在编译配置中额外设置替代内容。只要Jar文件正确添加到编译包中,import语句就能正常工作。
5. 测试最小化案例
创建一个仅调用NCTOOLBOX核心功能的简单MATLAB脚本,编译后测试,排除其他代码的干扰,快速定位是否是Jar添加不全或版本冲突问题。
内容的提问来源于stack exchange,提问作者gd-33

