欺骗JVM关于可用内核的数量(在Linux上)

出于某种目的,需要让JVM考虑在运行在具有N内核的机器上,而不是实际的内核数量(例如4内核而不是16 4内核)上运行。

JVM运行在基于Mandriva / Red Hat Linux内核的Linux构build下。

这个问题是临界情况,因为我期望这个问题的各种解决scheme。 这不是纯粹的Linuxpipe理问题,也不是纯粹的程序员问题。

那么…有什么想法?

以下Java程序将显示Java VM所看到的处理器数量:

 public class AvailableProcessors { public static void main(String... args) { System.out.println(Runtime.getRuntime().availableProcessors()); } } 

如果我在家用计算机上执行这个程序,它会打印4 ,这是实际的核心数量(包括超线程)。 现在让我们欺骗Java虚拟机,相信只有两个处理器:

 $ echo '0-1' > /tmp/online $ mount --bind /tmp/online /sys/devices/system/cpu/online 

如果我再次运行上述程序,它将打印2而不是4

这个技巧会影响系统上的所有进程。 但是,可以仅将效果限制在某些过程中。 Linux上的每个进程都可以有自己的挂载点名称空间。 例如,请参阅mount(2)手册页中的Pre-process命名空间部分。 例如,您可以使用lxc使用自己的挂载名称空间来启动新进程。

为了使Runtime.getRuntime().availableProcessors()返回任何你想要的,你可以使用LD_PRELOAD技巧来覆盖JVM_ActiveProcessorCount函数。 这是一个小程序来做到这一点:

 #include <stdlib.h> #include <unistd.h> int JVM_ActiveProcessorCount(void) { char* val = getenv("_NUM_CPUS"); return val != NULL ? atoi(val) : sysconf(_SC_NPROCESSORS_ONLN); } 

首先,制作一个这样的共享库:

 gcc -O3 -fPIC -shared -Wl,-soname,libnumcpus.so -o libnumcpus.so numcpus.c 

然后运行Java,如下所示:

 $ LD_PRELOAD=/path/to/libnumcpus.so _NUM_CPUS=2 java AvailableProcessors