我有一个带有以下签名的JNI方法:
JNIEXPORT jboolean JNICALL Java_MovieWriter_addFrameN(JNIEnv *env, jobject obj, jintArray jFrameBuffer, jlong jDuration);
此方法属于使用本机代码导出影片的程序。程序调用此方法向电影添加帧。 jFrameBuffer
是包含像素数据的int [],jDuration
是帧的持续时间。简单。
在短片中,一切似乎都运转正常。然而,对于5000+帧的电影,性能会受到影响(例如,执行此方法需要大约1秒钟,而通常情况下,对于相同数量的像素,它会在很短的时间内执行);并最终Java程序崩溃了,留下了我的以下hs日志(我只包括顶部,让我知道你是否想看到整个事情):
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (malloc) failed to allocate 691200 bytes for AllocateHeap
# Possible reasons:
# The system is out of physical RAM or swap space
# In 32 bit mode, the process size limit was hit
# Possible solutions:
# Reduce memory load on the system
# Increase physical memory or swap space
# Check if swap backing store is full
# Use 64 bit Java on a 64 bit OS
# Decrease Java heap size (-Xmx/-Xms)
# Decrease number of Java threads
# Decrease Java thread stack sizes (-Xss)
# Set larger code cache with -XX:ReservedCodeCacheSize=
# This output file may be truncated or incomplete.
#
# Out of Memory Error (memory/allocation.inline.hpp:61), pid=1880, tid=4008
#
# JRE version: Java(TM) SE Runtime Environment (7.0_45-b18) (build 1.7.0_45-b18)
# Java VM: Java HotSpot(TM) Client VM (24.45-b08 mixed mode windows-x86 )
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
我简化了问题以缩小问题范围,我的方法体现在如下:
JNIEXPORT jboolean JNICALL Java_MovieWriter_addFrameN(JNIEnv *env, jobject obj, jintArray jFrameBuffer, jlong jDuration) {
jsize jLength = env->GetArrayLength(jFrameBuffer);
int length = (int)jLength;
long duration = (long)jDuration;
//add a dummy frame
HRESULT hr = S_OK;
DWORD* pixels = new DWORD[length];
for (DWORD j = 0; j < length; j++) {
pixels[j] = 0x0000FF00;
}
hr = writer.addFrame(pixels, duration, true);
delete[] pixels;
return SUCCEEDED(hr);
}
我发现如果我对length
和duration
的值进行硬编码而不是将它们分别链接到jni值jLength
和jDuration
,那么性能问题就会出现问题不会发生。
int length = 640 * 480; // (int)jLength;
long duration = 10000000 / 25; // (long)jDuration;
这对我来说太惊人了。任何人都可以解释发生了什么以及如何解决问题?我甚至无法将基元从Java传递到C而没有性能问题的事实看起来很荒谬。我一定是做错了。
观察程序内存使用情况(使用任务管理器),表明它不会持续增加,所以我不相信我在任何地方都有任何重大泄漏,并且它远远低于内存限制我能成功击中做其他操作。
答案 0 :(得分:1)
好的,这就是发生的事情:确实是一个误解的例子。
我遇到性能延迟的原因&#39;是双重的:
当持续时间来自JNI时,它变化了......有时它很短,例如1/25秒,其他时间很长,例如3秒。当它很长时,Windows Media Foundation(我用它来编写帧)会将其分解为帧速大小的片段 - 所以需要3秒的持续时间帧3秒长,写入时间比1长1倍/ 25秒帧,如果帧速率是每秒25帧。所以,这是我认为的性能延迟的一部分,但实际上,它只是做了更多的工作。精细。这是有道理的。
第二个方面与以下事实有关:在向我的Windows Media Foundation IMFSinkWriter发送大约100,000帧之后,它会陷入困境。这是神秘的关键。事实证明,需要每秒调用一次IMFSinkWriter-&gt; NotifyEndOfSegment以防止这种情况发生。在任何地方我都没有看到这个记录,男孩这样做会让我感到非常悲伤。