为什么在“make”下运行会改变共享库加载地址?

时间:2011-02-07 14:37:37

标签: java linux makefile shared-libraries

一位同事在运行命令时发现了

java -Xmx1024m -version

从makefile中获取消息'Failed to instantiate heap; 1G requested'

但是从命令行运行它可以正常工作。这是在SUSE Linux Enterprise Server 11上使用32位JVM(64位工作正常)。

经过进一步调查后,他发现:

  

通常是java共享库   在流程结束时加载   地址空间,所以周围的地址   0x7 ...如果java正在运行java   进程,库被加载   地址空间的中间位置   地址大约为0x4 ....

有没有人知道为什么make会导致库被加载到不同的位置,并且无论如何都要阻止它?

2 个答案:

答案 0 :(得分:1)

加载地址仅是首选加载地址。如果已经映射并使用了另一个so / dll,那么so / dll将被重新定位。无论如何,ASLR情况更糟,你永远不知道这些东西在用户空间中可见的地方。

编辑:

我可以用2GB(-Xmx2048m)重现问题,但不知道技术上到底是什么问题。我认为这与过程与制作/产生方式有关的方式有关

jaap@ubuntu-desktop:~$ make
java -Xmx2048m -version
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
make: *** [all] Error 1

答案 1 :(得分:0)

我看到了类似的效果并追查原因:

  • 动态库的加载地址通常是mmap(0)分配的任何内容。所以这里的不同之处在于内核将内存放入进程地址spcace。
  • 内核用于从低用户空间地址向上分配内存,但切换到自上而下。请参阅https://lwn.net/Articles/91829/
  • 如果在RLIMIT_STACK设置为无穷大的情况下启动子进程,内核将切换到旧的(传统)自下而上的分配(传统顺序也可以强制使用个性位,但这可能不是这里发生的事情)。 / LI>
  • make 3.81引入了一个错误,它启动了RLIMIT_STACK设置为无穷大的子进程
  • 修复了make 3.82:https://savannah.gnu.org/bugs/?22010
  • 在至少一个商业发行版中,make为3.81,但似乎已应用此错误修复,并且不会受到内存订单问题的影响。

因此,如果您使用的是标准的3.81 make,那很可能就是问题所在。如果没有,那么可能还有其他东西在子进程中将RLIMIT_STACK设置为无穷大。如果它不是RLIMIT_STACK,那可能就是个性。在命令行和make下查看/ proc / self / personality,看看它是否设置了200000。