Skip to content

Instantly share code, notes, and snippets.

@thomasdarimont
Last active January 11, 2024 08:03
Show Gist options
  • Save thomasdarimont/ca5ca088a9007eb25dff677a8ace3ff1 to your computer and use it in GitHub Desktop.
Save thomasdarimont/ca5ca088a9007eb25dff677a8ace3ff1 to your computer and use it in GitHub Desktop.
Using LD_PRELOAD to pass a fake CPU count to Java on Linux

Build shared library

gcc -shared -fPIC fake-cpu-count.c -o fake-cpu-count.so -ldl

Compile ReportCpuCount

javac ReportCpuCount.java

Run normally

java -cp . ReportCpuCount
#Found 8 CPUs
#...

Run with fake-cpu-count library

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);
}
}
}
@thomasdarimont
Copy link
Author

thomasdarimont commented May 15, 2018

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...

@microhardsmith
Copy link

It seems to be not working on JDK21, the underling mechanism that Runtime.getRuntime().availableProcessors() uses seems to have changed in Linux

@thomasdarimont
Copy link
Author

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().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment