出于某种目的,需要让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