Я смог получить то, что мне было нужно, используя опцию "vfprintf", описанную здесь:
http://java.sun.com/products/jdk/faq/jnifaq-old.html
хотя я использовал опции jdk1.2. Этот фрагмент кода обобщает мое решение:
static string jniErrors;
static jint JNICALL my_vfprintf(FILE *fp, const char *format, va_list args)
{
char buf[1024];
vsnprintf(buf, sizeof(buf), format, args);
jniErrors += buf;
return 0;
}
...
JavaVMOption options[1];
options[0].optionString = "vfprintf";
options[0].extraInfo = my_vfprintf;
JavaVMInitArgs vm_args;
memset(&vm_args, 0, sizeof(vm_args));
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.version = JNI_VERSION_1_4;
vm_args.ignoreUnrecognized = JNI_FALSE;
JNIEnv env;
JavaVM jvm;
jint res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
if (res != JNI_OK)
setError(jniErrors);
jniErrors.clear();
Также интересно то, что я не мог на протяжении всей жизни правильно захватывать stdout или stderr с помощью трюков freopen или dup2. Я мог бы загрузить свою собственную dll и правильно перенаправить, но не jvm. В любом случае, так лучше, потому что я хотел ошибок в памяти, а не в файле.