Attempt to load versioned shared objects in Java
Since TensorFlow 1.14.0, libtensorflow_framework.so has been packaged as a versioned shared object. This change attempts to support that naming scheme in the Java NativeLibrary loader. If libtensorflow_framework.so is not present and a major version number can be determined, the loader will attempt to find libtensorflow_framework.so.<majorVersion>, where <majorVersion> is determined from the manifest of the JAR from which the NativeLibrary class was loaded. On darwin, the loader will look for libtensorflow_framework.<majorVersion>.so. PiperOrigin-RevId: 260749010
This commit is contained in:
parent
af916f80c0
commit
a4a4057748
@ -65,7 +65,7 @@ final class NativeLibrary {
|
|||||||
NativeLibrary.class.getClassLoader().getResourceAsStream(jniResourceName);
|
NativeLibrary.class.getClassLoader().getResourceAsStream(jniResourceName);
|
||||||
// Extract the JNI's dependency
|
// Extract the JNI's dependency
|
||||||
final String frameworkLibName =
|
final String frameworkLibName =
|
||||||
maybeAdjustForMacOS(System.mapLibraryName("tensorflow_framework"));
|
getVersionedLibraryName(System.mapLibraryName("tensorflow_framework"));
|
||||||
final String frameworkResourceName = makeResourceName(frameworkLibName);
|
final String frameworkResourceName = makeResourceName(frameworkLibName);
|
||||||
log("frameworkResourceName: " + frameworkResourceName);
|
log("frameworkResourceName: " + frameworkResourceName);
|
||||||
final InputStream frameworkResource =
|
final InputStream frameworkResource =
|
||||||
@ -126,22 +126,66 @@ final class NativeLibrary {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String maybeAdjustForMacOS(String libFilename) {
|
private static boolean resourceExists(String baseName) {
|
||||||
if (!System.getProperty("os.name").contains("OS X")) {
|
return NativeLibrary.class.getClassLoader().getResource(makeResourceName(baseName)) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getVersionedLibraryName(String libFilename) {
|
||||||
|
// If the resource exists as an unversioned file, return that.
|
||||||
|
if (resourceExists(libFilename)) {
|
||||||
return libFilename;
|
return libFilename;
|
||||||
}
|
}
|
||||||
// This is macOS, and the TensorFlow release process might have setup dependencies on
|
|
||||||
// libtensorflow_framework.so instead of libtensorflow_framework.dylib. Adjust for that.
|
final String versionName = getMajorVersionNumber();
|
||||||
final ClassLoader cl = NativeLibrary.class.getClassLoader();
|
|
||||||
if (cl.getResource(makeResourceName(libFilename)) != null) {
|
// If we're on darwin, the versioned libraries look like blah.1.dylib.
|
||||||
return libFilename;
|
final String darwinSuffix = ".dylib";
|
||||||
|
if (libFilename.endsWith(darwinSuffix)) {
|
||||||
|
final String prefix = libFilename.substring(0, libFilename.length() - darwinSuffix.length());
|
||||||
|
if (versionName != null) {
|
||||||
|
final String darwinVersionedLibrary = prefix + "." + versionName + darwinSuffix;
|
||||||
|
if (resourceExists(darwinVersionedLibrary)) {
|
||||||
|
return darwinVersionedLibrary;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If we're here, we're on darwin, but we couldn't figure out the major version number. We
|
||||||
|
// already tried the library name without any changes, but let's do one final try for the
|
||||||
|
// library with a .so suffix.
|
||||||
|
final String darwinSoName = prefix + ".so";
|
||||||
|
if (resourceExists(darwinSoName)) {
|
||||||
|
return darwinSoName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (libFilename.endsWith(".so")) {
|
||||||
|
// Libraries ending in ".so" are versioned like "libfoo.so.1", so try that.
|
||||||
|
final String versionedSoName = libFilename + "." + versionName;
|
||||||
|
if (versionName != null && resourceExists(versionedSoName)) {
|
||||||
|
return versionedSoName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// liftensorflow_framework.dylib not found, try libtensorflow_framework.so
|
|
||||||
final String suffix = ".dylib";
|
// Otherwise, we've got no idea.
|
||||||
if (!libFilename.endsWith(suffix)) {
|
return libFilename;
|
||||||
return libFilename;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the major version number of this TensorFlow Java API, or {@code null} if it cannot be
|
||||||
|
* determined.
|
||||||
|
*/
|
||||||
|
private static String getMajorVersionNumber() {
|
||||||
|
String version = NativeLibrary.class.getPackage().getImplementationVersion();
|
||||||
|
// expecting a string like 1.14.0, we want to get the first '1'.
|
||||||
|
int dotIndex;
|
||||||
|
if (version == null || (dotIndex = version.indexOf('.')) == -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String majorVersion = version.substring(0, dotIndex);
|
||||||
|
try {
|
||||||
|
Integer.parseInt(majorVersion);
|
||||||
|
return majorVersion;
|
||||||
|
} catch (NumberFormatException unused) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return libFilename.substring(0, libFilename.length() - suffix.length()) + ".so";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String extractResource(
|
private static String extractResource(
|
||||||
|
Loading…
Reference in New Issue
Block a user