diff --git a/core/java/src/freenet/support/CPUInformation/CPUID.java b/core/java/src/freenet/support/CPUInformation/CPUID.java index 921f497ddedb924f5f776e44c865c59fb8bfa79a..3d9c8fe240629f32fc7cece010d29809e5bef4ba 100644 --- a/core/java/src/freenet/support/CPUInformation/CPUID.java +++ b/core/java/src/freenet/support/CPUInformation/CPUID.java @@ -45,19 +45,35 @@ public class CPUID { private static boolean _doLog = System.getProperty("jcpuid.dontLog") == null && I2PAppContext.getGlobalContext().isRouterContext(); - //.matches() is a java 1.4+ addition, using a simplified version for 1.3+ - //private static final boolean isX86 = System.getProperty("os.arch").toLowerCase().matches("i?[x0-9]86(_64)?"); - private static final boolean isX86 = (-1 != System.getProperty("os.arch").indexOf("86")); + private static final boolean isX86 = System.getProperty("os.arch").contains("86"); private static final String libPrefix = (System.getProperty("os.name").startsWith("Win") ? "" : "lib"); private static final String libSuffix = (System.getProperty("os.name").startsWith("Win") ? ".dll" : ".so"); + private static final boolean isWindows = System.getProperty("os.name").toLowerCase().contains("windows"); + private static final boolean isLinux = System.getProperty("os.name").toLowerCase().contains("linux"); + private static final boolean isFreebsd = System.getProperty("os.name").toLowerCase().contains("freebsd"); + /** + * This isn't always correct. + * http://stackoverflow.com/questions/807263/how-do-i-detect-which-kind-of-jre-is-installed-32bit-vs-64bit + * http://mark.koli.ch/2009/10/javas-osarch-system-property-is-the-bitness-of-the-jre-not-the-operating-system.html + * http://mark.koli.ch/2009/10/reliably-checking-os-bitness-32-or-64-bit-on-windows-with-a-tiny-c-app.html + * sun.arch.data.model not on all JVMs + * sun.arch.data.model == 64 => 64 bit processor + * sun.arch.data.model == 32 => A 32 bit JVM but could be either 32 or 64 bit processor or libs + * os.arch contains "64" could be 32 or 64 bit libs + */ + private static final boolean is64 = "64".equals(System.getProperty("sun.arch.data.model")) || + System.getProperty("os.arch").contains("64"); + static { loadNative(); } - //A class that can (amongst other things I assume) represent the state of the - //different CPU registers after a call to the CPUID assembly method + /** + * A class that can (amongst other things I assume) represent the state of the + * different CPU registers after a call to the CPUID assembly method + */ protected static class CPUIDResult { final int EAX; final int EBX; @@ -151,12 +167,14 @@ public class CPUID { return c.ECX; } - //Returns a CPUInfo item for the current type of CPU - //If I could I would declare this method in a interface named - //CPUInfoProvider and implement that interface in this class. - //This would make it easier for other people to understand that there - //is nothing preventing them from coding up new providers, probably using - //other detection methods than the x86-only CPUID instruction + /** + * Returns a CPUInfo item for the current type of CPU + * If I could I would declare this method in a interface named + * CPUInfoProvider and implement that interface in this class. + * This would make it easier for other people to understand that there + * is nothing preventing them from coding up new providers, probably using + * other detection methods than the x86-only CPUID instruction + */ public static CPUInfo getInfo() throws UnknownCPUException { if(!_nativeOk) @@ -506,7 +524,7 @@ public class CPUID { } - /** + /** * <p>Do whatever we can to load up the native library. * If it can find a custom built jcpuid.dll / libjcpuid.so, it'll use that. Otherwise * it'll try to look in the classpath for the correct library (see loadFromResource). @@ -547,6 +565,8 @@ public class CPUID { /** * <p>Try loading it from an explictly built jcpuid.dll / libjcpuid.so</p> + * The file name must be (e.g. on linux) either libjcpuid.so or libjcpuid-x86-linux.so. + * This method does not search for a filename with "_64" in it. * * @return true if it was loaded successfully, else false * @@ -558,6 +578,13 @@ public class CPUID { } catch (UnsatisfiedLinkError ule) { // fallthrough, try the OS-specific filename } + + // Don't bother trying a 64 bit filename variant. + + // Note this is unlikely to succeed on a standard installation, since when we extract the library + // in loadResource() below, we save it as jcpuid.dll / libcupid.so. + // However, a distribution may put the file in, e.g., /usr/lib/jni/ + // with the libjcpuid-x86-linux.so name. try { System.loadLibrary(getLibraryMiddlePart()); return true; @@ -578,14 +605,25 @@ public class CPUID { * so we transparently support read-only base dirs. * </p> * + * This tries the 64 bit version first if we think we may be 64 bit. + * Then it tries the 32 bit version. + * * @return true if it was loaded successfully, else false * */ private static final boolean loadFromResource() { - String resourceName = getResourceName(); - if (resourceName == null) return false; - URL resource = CPUID.class.getClassLoader().getResource(resourceName); + URL resource = null; + // try 64 bit first, if getResourceName64() returns non-null + String resourceName = getResourceName64(); + if (resourceName != null) + resource = CPUID.class.getClassLoader().getResource(resourceName); + if (resource == null) { + // now try 32 bit + resourceName = getResourceName(); + resource = CPUID.class.getClassLoader().getResource(resourceName); + } + if (resource == null) { if (_doLog) System.err.println("WARNING: Resource name [" + resourceName + "] was not found"); @@ -599,7 +637,6 @@ public class CPUID { InputStream libStream = resource.openStream(); outFile = new File(I2PAppContext.getGlobalContext().getTempDir(), filename); fos = new FileOutputStream(outFile); - // wtf this was 4096*1024 which is really excessive for a roughly 4KB file byte buf[] = new byte[4096]; while (true) { int read = libStream.read(buf); @@ -633,14 +670,24 @@ public class CPUID { return true; } + /** @return non-null */ private static final String getResourceName() { return getLibraryPrefix()+getLibraryMiddlePart()+"."+getLibrarySuffix(); } + /** + * @return null if not on a 64 bit platform + * @since 0.8.7 + */ + private static final String getResourceName64() { + if (!is64) + return null; + return getLibraryPrefix() + get64LibraryMiddlePart() + "." + getLibrarySuffix(); + } + private static final String getLibraryPrefix() { - boolean isWindows =System.getProperty("os.name").toLowerCase().indexOf("windows") != -1; if(isWindows) return ""; else @@ -648,21 +695,27 @@ public class CPUID { } private static final String getLibraryMiddlePart(){ - boolean isWindows =(System.getProperty("os.name").toLowerCase().indexOf("windows") != -1); - boolean isLinux =(System.getProperty("os.name").toLowerCase().indexOf("linux") != -1); - boolean isFreebsd =(System.getProperty("os.name").toLowerCase().indexOf("freebsd") != -1); if(isWindows) return "jcpuid-x86-windows"; // The convention on Windows - if(isLinux) - return "jcpuid-x86-linux"; // The convention on linux... if(isFreebsd) return "jcpuid-x86-freebsd"; // The convention on freebsd... - throw new RuntimeException("Dont know jcpuid library name for os type '"+System.getProperty("os.name")+"'"); + //throw new RuntimeException("Dont know jcpuid library name for os type '"+System.getProperty("os.name")+"'"); + // use linux as the default, don't throw exception + return "jcpuid-x86-linux"; + } + + /** @since 0.8.7 */ + private static final String get64LibraryMiddlePart() { + if(isWindows) + return "jcpuid-x86_64-windows"; + if(isFreebsd) + return "jcpuid-x86_64-freebsd"; + // use linux as the default, don't throw exception + return "jcpuid-x86_64-linux"; } private static final String getLibrarySuffix() { - boolean isWindows =System.getProperty("os.name").toLowerCase().indexOf("windows") != -1; if(isWindows) return "dll"; else