gcc -shared -fPIC fake-cpu-count.c -o fake-cpu-count.so -ldl
javac ReportCpuCount.java
java -cp . ReportCpuCount
#Found 8 CPUs
#...
LD_PRELOAD=./fake-cpu-count.so java -cp . ReportCpuCount
#Found 2 CPUs
#...
#define _GNU_SOURCE | |
#include "stdlib.h" | |
#include <unistd.h> | |
#include <dlfcn.h> | |
typedef long int (*orig_sysconf_f_type)(int __name); | |
long sysconf(int name){ | |
orig_sysconf_f_type orig_sysconf; | |
orig_sysconf = (orig_sysconf_f_type)dlsym(RTLD_NEXT,"sysconf"); | |
if (name == _SC_NPROCESSORS_CONF){ | |
return 2; | |
} | |
return orig_sysconf(name); | |
} |
public class ReportCpuCount { | |
public static void main(String[] args) throws Exception{ | |
while(true){ | |
System.out.printf("#Found %d CPUs%n", Runtime.getRuntime().availableProcessors()); | |
Thread.sleep(1000); | |
} | |
} | |
} |
It seems to be not working on JDK21, the underling mechanism that Runtime.getRuntime().availableProcessors()
uses seems to have changed in Linux
The example is almost 5 years old, so that was to expect :), but ood to know. In the current JDK there is still code that queries the sysconf property mentioned above:
https://github.com/openjdk/jdk/blob/master/src/hotspot/os/linux/os_linux.cpp#L432
However, there seems to be another abstraction wrapped around that, which is container/cgroups aware which then overrides the actual value in order to support dynamic cpu settings.
See:
With that said, the example is just to demonstrate the mechanism, for another example one could try to replace the native logic behing System.currentTimeMillis().
This example could be extended to read the available CPUs from an env variable or cgroups. This example comes from a time before JVMs were aware of any container limits...