16
16
17
17
package io .objectbox .internal ;
18
18
19
+ import io .objectbox .BoxStore ;
19
20
import org .greenrobot .essentials .io .IoUtils ;
20
21
22
+ import javax .annotation .Nullable ;
21
23
import java .io .BufferedInputStream ;
22
24
import java .io .BufferedOutputStream ;
25
+ import java .io .BufferedReader ;
23
26
import java .io .File ;
24
27
import java .io .FileOutputStream ;
25
28
import java .io .IOException ;
26
29
import java .io .InputStream ;
30
+ import java .io .InputStreamReader ;
27
31
import java .io .OutputStream ;
28
32
import java .lang .reflect .InvocationTargetException ;
29
33
import java .lang .reflect .Method ;
30
34
import java .net .URL ;
31
35
import java .net .URLConnection ;
32
36
33
- import io .objectbox .BoxStore ;
34
-
35
37
/**
36
38
* Separate class, so we can mock BoxStore.
37
39
*/
@@ -103,13 +105,21 @@ public class NativeLibraryLoader {
103
105
String osArch = System .getProperty ("os.arch" );
104
106
String sunArch = System .getProperty ("sun.arch.data.model" );
105
107
String message = String .format (
106
- "Loading ObjectBox native library failed: vendor=%s,os=%s,os.arch=%s,sun.arch=%s,android=%s,linux=%s" ,
107
- vendor , osName , osArch , sunArch , android , isLinux
108
+ "[ObjectBox] Loading native library failed, please report this to us: " +
109
+ "vendor=%s,os=%s,os.arch=%s,model=%s,android=%s,linux=%s,machine=%s" ,
110
+ vendor , osName , osArch , sunArch , android , isLinux , getCpuArchOSOrNull ()
108
111
);
109
112
throw new LinkageError (message , e ); // UnsatisfiedLinkError does not allow a cause; use its super class
110
113
}
111
114
}
112
115
116
+ /**
117
+ * Get CPU architecture of the JVM (Note: this can not be used for Android, Android decides arch on its own
118
+ * and looks for library in appropriately named folder).
119
+ * <p>
120
+ * Note that this may not be the architecture of the actual hardware
121
+ * (e.g. when running a x86 JVM on an amd64 machine).
122
+ */
113
123
private static String getCpuArch () {
114
124
String osArch = System .getProperty ("os.arch" );
115
125
String cpuArch = null ;
@@ -119,34 +129,70 @@ private static String getCpuArch() {
119
129
cpuArch = "x64" ;
120
130
} else if (osArch .equalsIgnoreCase ("x86" )) {
121
131
cpuArch = "x86" ;
132
+ } else if ("aarch64" .equals (osArch ) || osArch .startsWith ("armv8" ) || osArch .startsWith ("arm64" )) {
133
+ // 64-bit ARM
134
+ cpuArch = "arm64" ;
122
135
} else if (osArch .startsWith ("arm" )) {
123
- switch (osArch ) {
124
- case "armv7" :
125
- case "armv7l" :
126
- case "armeabi-v7a" : // os.arch "armeabi-v7a" might be Android only, but let's try anyway...
127
- cpuArch = "armv7" ;
128
- break ;
129
- case "arm64-v8a" :
130
- cpuArch = "arm64" ;
131
- break ;
132
- case "armv6" :
133
- cpuArch = "armv6" ;
134
- break ;
135
- default :
136
- cpuArch = "armv6" ; // Lowest version we support
137
- System .err .println ("Unknown os.arch \" " + osArch + "\" - ObjectBox is defaulting to " + cpuArch );
138
- break ;
136
+ // 32-bit ARM
137
+ if (osArch .startsWith ("armv7" ) || osArch .startsWith ("armeabi-v7" )) {
138
+ cpuArch = "armv7" ;
139
+ } else if (osArch .startsWith ("armv6" )) {
140
+ cpuArch = "armv6" ;
141
+ } else if ("arm" .equals (osArch )) {
142
+ // JVM may just report "arm" for any 32-bit ARM, so try to check with OS.
143
+ String cpuArchOSOrNull = getCpuArchOSOrNull ();
144
+ if (cpuArchOSOrNull != null ) {
145
+ String cpuArchOS = cpuArchOSOrNull .toLowerCase ();
146
+ if (cpuArchOS .startsWith ("armv7" )) {
147
+ cpuArch = "armv7" ;
148
+ } else if (cpuArchOS .startsWith ("armv6" )){
149
+ cpuArch = "armv6" ;
150
+ } // else use fall back below.
151
+ } // else use fall back below.
152
+ }
153
+ if (cpuArch == null ) {
154
+ // Fall back to lowest supported 32-bit ARM version.
155
+ cpuArch = "armv6" ;
156
+ System .err .printf ("[ObjectBox] 32-bit ARM os.arch unknown (will use %s), " +
157
+ "please report this to us: os.arch=%s, machine=%s%n" ,
158
+ cpuArch , osArch , getCpuArchOSOrNull ());
139
159
}
140
160
}
141
161
}
162
+ // If os.arch is not covered above try a x86 version based on JVM bit-ness.
142
163
if (cpuArch == null ) {
143
164
String sunArch = System .getProperty ("sun.arch.data.model" );
144
- cpuArch = "32" .equals (sunArch ) ? "x86" : "x64" ;
145
- System .err .println ("Unknown os.arch \" " + osArch + "\" - ObjectBox is defaulting to " + cpuArch );
165
+ if ("64" .equals (sunArch )) {
166
+ cpuArch = "x64" ;
167
+ } else if ("32" .equals (sunArch )) {
168
+ cpuArch = "x86" ;
169
+ } else {
170
+ cpuArch = "unknown" ;
171
+ }
172
+ System .err .printf ("[ObjectBox] os.arch unknown (will use %s), " +
173
+ "please report this to us: os.arch=%s, model=%s, machine=%s%n" ,
174
+ cpuArch , osArch , sunArch , getCpuArchOSOrNull ());
146
175
}
147
176
return cpuArch ;
148
177
}
149
178
179
+ /**
180
+ * Get architecture using operating system tools. Currently only Linux is supported (using uname).
181
+ */
182
+ @ Nullable
183
+ private static String getCpuArchOSOrNull () {
184
+ String archOrNull = null ;
185
+ try {
186
+ // Linux
187
+ Process exec = Runtime .getRuntime ().exec ("uname -m" );
188
+ BufferedReader reader = new BufferedReader (new InputStreamReader (exec .getInputStream ()));
189
+ archOrNull = reader .readLine ();
190
+ reader .close ();
191
+ } catch (Exception ignored ) {
192
+ }
193
+ return archOrNull ;
194
+ }
195
+
150
196
private static void checkUnpackLib (String filename ) {
151
197
String path = "/native/" + filename ;
152
198
URL resource = NativeLibraryLoader .class .getResource (path );
0 commit comments