我在遗留系统上工作,该系统具有需要调用Java代码的VB6应用程序。我们使用的解决方案是让VB应用程序调用C ++ DLL,它使用JNI来调用Java代码。有点时髦,但实际上效果很好。但是,我正在转向一个新的开发盒,我刚刚遇到了一个严重的问题。构建的VB应用程序在新框中运行正常,但是当我尝试从VB运行它时,dll无法加载VM,从JNI_CreateJavaVM获取返回代码-4(JNI_ENOMEM)。
构建的应用程序和VB都调用完全相同的dll,我已经尝试使用Java 1.5和1.6。我已经尝试了建议here(将stdout和stderr重定向到文件,添加vfprint选项,添加-Xcheck:jni选项),但无济于事。我似乎无法从jvm中获取任何其他信息。据我所知,新的盒子配置与旧盒子(安装的软件,路径,类路径等)几乎相同,并且两者都运行相同版本的Windows Server 2003.新机器是x64具有更多内存的盒子(4GB而不是2GB),但它运行的是32位Windows。
关于还有什么可以研究的任何建议或想法?以更合理的方式重写整个事情不是一个选择 - 我需要找到一种方法让dll加载jvm而不用认为它是内存不足。任何帮助将不胜感激。
答案 0 :(得分:1)
答案 1 :(得分:1)
仅供参考 - 我找到了以下非常有用的文章:https://forums.oracle.com/forums/thread.jspa?messageID=6463655
我将在这里重复一些非常有用的代码,因为我不确定我是否相信Oracle会保留上述论坛。
当我设置我的JVM时,我使用getMaxHeapAvailable()调用,然后相应地设置我的堆空间(-Xmxm) - 适用于RAM较少的工作站,而不必惩罚具有大量RAM的用户。
bool canAllocate(DWORD bytes)
{
LPVOID lpvBase;
lpvBase = VirtualAlloc(NULL, bytes, MEM_RESERVE, PAGE_READWRITE);
if (lpvBase == NULL) return false;
VirtualFree(lpvBase, 0, MEM_RELEASE);
return true;
}
int getMaxHeapAvailable(int permGenMB, int maxHeapMB)
{
DWORD originalMaxHeapBytes = 0;
DWORD maxHeapBytes = 0;
int numMemChunks = 0;
SYSTEM_INFO sSysInfo;
DWORD maxPermBytes = permGenMB * NUM_BYTES_PER_MB; // Perm space is in addition to the heap size
DWORD numBytesNeeded = 0;
GetSystemInfo(&sSysInfo);
// jvm aligns as follows:
// quoted from size_t GenCollectorPolicy::compute_max_alignment() of jdk 7 hotspot code:
// The card marking array and the offset arrays for old generations are
// committed in os pages as well. Make sure they are entirely full (to
// avoid partial page problems), e.g. if 512 bytes heap corresponds to 1
// byte entry and the os page size is 4096, the maximum heap size should
// be 512*4096 = 2MB aligned.
// card_size computation from CardTableModRefBS::SomePublicConstants of jdk 7 hotspot code
int card_shift = 9;
int card_size = 1 << card_shift;
DWORD alignmentBytes = sSysInfo.dwPageSize * card_size;
maxHeapBytes = maxHeapMB * NUM_BYTES_PER_MB;
// make it fit in the alignment structure
maxHeapBytes = maxHeapBytes + (maxHeapBytes % alignmentBytes);
numMemChunks = maxHeapBytes / alignmentBytes;
originalMaxHeapBytes = maxHeapBytes;
// loop and decrement requested amount by one chunk
// until the available amount is found
numBytesNeeded = maxHeapBytes + maxPermBytes;
while (!canAllocate(numBytesNeeded + 50*NUM_BYTES_PER_MB) && numMemChunks > 0) // 50 is an overhead fudge factory per https://forums.oracle.com/forums/thread.jspa?messageID=6463655 (they had 28, I'm bumping it 'just in case')
{
numMemChunks --;
maxHeapBytes = numMemChunks * alignmentBytes;
numBytesNeeded = maxHeapBytes + maxPermBytes;
}
if (numMemChunks == 0) return 0;
// we can allocate the requested size, return it now
if (maxHeapBytes == originalMaxHeapBytes) return maxHeapMB;
// calculate the new MaxHeapSize in megabytes
return maxHeapBytes / NUM_BYTES_PER_MB;
}
答案 2 :(得分:0)
我遇到了“克劳斯”所描述的同样问题,并阅读了“http://support.microsoft.com/kb/126962”。按照上述文章中的描述更改了注册表。我将我的更改扩展为:“%SystemRoot%\ system32 \ csrss.exe ObjectDirectory = \ Windows SharedSection = 3072,3072,3072 Windows = On SubSystemType = Windows ServerDll = basesrv,1 ServerDll = winsrv:UserServerDllInitialization,3 ServerDll = winsrv:ConServerDllInitialization ,2 ProfileControl = Off MaxRequestThreads = 16“
要查看的字段是“SharedSection = 3072,3072,3072”。它解决了我的问题,但由于这种变化,我可能会产生副作用。