Skip to content

Instantly share code, notes, and snippets.

@thomasdarimont
Last active May 26, 2025 12:15
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().

@fumiyas
Copy link

fumiyas commented May 26, 2025

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