Skip to content

Instantly share code, notes, and snippets.

@thomasdarimont
Last active May 26, 2025 12:15
Show Gist options
  • Select an option

  • Save thomasdarimont/ca5ca088a9007eb25dff677a8ace3ff1 to your computer and use it in GitHub Desktop.

Select an option

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

thomasdarimont commented May 15, 2018

Copy link
Copy Markdown
Author

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
Copy Markdown

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
Copy Markdown
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

fumiyas commented May 26, 2025

Copy link
Copy Markdown

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