Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion cdm/core/src/main/java/ucar/nc2/NetcdfFileWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ protected NetcdfFileWriter(Version version, String location, boolean isExisting,
if (version.useJniIosp()) {
IOServiceProviderWriter spi;
try {
// Nc4Iosp.setLibraryAndPath(path, name);
Class iospClass = this.getClass().getClassLoader().loadClass("ucar.nc2.jni.netcdf.Nc4Iosp");
Constructor<IOServiceProviderWriter> ctor = iospClass.getConstructor(Version.class);
spi = ctor.newInstance(version);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2018 John Caron and University Corporation for Atmospheric Research/Unidata
* Copyright (c) 1998-2025 John Caron and University Corporation for Atmospheric Research/Unidata
* See LICENSE for license information.
*/

Expand Down Expand Up @@ -269,7 +269,7 @@ public static void read(org.jdom2.Element root, StringBuilder errlog) {
// so we cannot refer to the Nc4Iosp.class and NetcdfClibrary.class object.
String nc4IospClassName = "ucar.nc2.jni.netcdf.Nc4Iosp";
// The setLibraryAndPath method from Nc4Iosp has been deprecated
// and splited into separated class: NetcdfClibrary
// and split into separated class: NetcdfClibrary
String netcdfClibraryClassName = "ucar.nc2.ffi.netcdf.NetcdfClibrary";
/*
* <Netcdf4Clibrary>
Expand All @@ -285,8 +285,9 @@ public static void read(org.jdom2.Element root, StringBuilder errlog) {
if (path != null && name != null) {
// reflection is used to decouple optional jars
try {
Class netcdfClibraryClass = RuntimeConfigParser.class.getClassLoader().loadClass(netcdfClibraryClassName);
Method method = netcdfClibraryClass.getMethod("setLibraryAndPath", String.class, String.class);
Class<?> netcdfClibraryClass =
RuntimeConfigParser.class.getClassLoader().loadClass(netcdfClibraryClassName);
Method method = netcdfClibraryClass.getMethod("setLibraryNameAndPath", String.class, String.class);
method.invoke(null, path, name); // static method has null for object
} catch (Throwable e) {
errlog.append(netcdfClibraryClassName + " is not on classpath\n");
Expand Down
3 changes: 2 additions & 1 deletion docs/src/site/pages/netcdfJava/netcdf4Clibrary.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ For standalone CDM library use, you can:
* create a system environment variable: `JNA_PATH=/path/to/library`
* set a Java property on the command line: `-Djna.library.path=/path/to/library`
* set the library path and name in the runtime configuration file
* directly call `Nc4Iosp.setLibraryAndPath()` from your Java program
* directly call `ucar.nc2.ffi.netcdf.NetcdfClibrary.setLibraryNameAndPath` from your Java program
(Note: this must be called prior to calling `isLibraryPresent()` or `getForeignFunctionInterface()` as the C library can only be successfully loaded once)

In all cases, we recommended that you use an absolute path to specify the library location.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Runtime loading
last_updated: 2021-06-08
last_updated: 2025-08-12
sidebar: netcdfJavaTutorial_sidebar
permalink: runtime_loading.html
toc: false
Expand Down
1 change: 1 addition & 0 deletions netcdf4/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencies {
testImplementation project(':cdm-test-utils')

testImplementation 'com.google.truth:truth'
testImplementation 'org.jdom:jdom2'

testRuntimeOnly 'ch.qos.logback:logback-classic'
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2025 University Corporation for Atmospheric Research/Unidata
* See LICENSE.txt for license information.
*/

package ucar.nc2.util.xml;

import static com.google.common.truth.Truth.assertThat;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Paths;
import org.junit.Test;

public class TestRuntimeConfigParser {
@Test
public void testReflection() throws IOException {
// not testing that the loading actually work, but testing that the reflection
// calls in the RuntimeConfigParser work
File nj22config =
Paths.get("src/test/resources/runtimeConfig/nj22Config.xml").toAbsolutePath().normalize().toFile();
StringBuilder errlog = new StringBuilder();
try (FileInputStream fis = new FileInputStream(nj22config)) {
RuntimeConfigParser.read(fis, errlog);
}
String err = errlog.toString();
assertThat(err).isNotEmpty();
// since this test lives in the netcdf4 subproject, we should only see
// the "is not on classpath" message if the reflection call used in the
// RuntimeConfigParser code fails
assertThat(err).doesNotContain("is not on classpath");
}
}
7 changes: 7 additions & 0 deletions netcdf4/src/test/resources/runtimeConfig/nj22Config.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<nj22Config>
<Netcdf4Clibrary>
<libraryPath>/not/a/real/path</libraryPath>
<libraryName>netcdf</libraryName>
<useForReading>false</useForReading>
</Netcdf4Clibrary>
</nj22Config>