Java 上下文切换本机线程可以';不连接到JVM

Java 上下文切换本机线程可以';不连接到JVM,java,linux,boost,java-native-interface,Java,Linux,Boost,Java Native Interface,我们有一个Java服务器(Linux 64位)应用程序,它使用本机代码进行处理。本机代码还处理所有多线程问题,最近通过使用boost::context的光纤交换功能得到了增强 我们现在面临的问题是,对于光纤交换线程,AttachCurrentThread失败。经过长时间的调试和测试,我们找到了原因:JVM似乎拒绝使用不同于创建时给出的堆栈指针的线程 我们通过简单地从一个pthread连接到JVM来验证这一点,该pthread带有修改过的(但有效的)rsp,当rsp被修改时,它会失败 一个可能的修

我们有一个Java服务器(Linux 64位)应用程序,它使用本机代码进行处理。本机代码还处理所有多线程问题,最近通过使用
boost::context
的光纤交换功能得到了增强

我们现在面临的问题是,对于光纤交换线程,
AttachCurrentThread
失败。经过长时间的调试和测试,我们找到了原因:JVM似乎拒绝使用不同于创建时给出的堆栈指针的线程

我们通过简单地从一个pthread连接到JVM来验证这一点,该pthread带有修改过的(但有效的)
rsp
,当
rsp
被修改时,它会失败

一个可能的修复方法将引入某种事件处理机制,以将回调与光纤交换线程解耦,但我确实希望避免这种情况

有人知道解决这个问题的方法吗

是否可以禁用堆栈检查(Oracle Java 1.7.0_40,64位)


我们是否可以修改本机pthread以指向正确的堆栈帧(我怀疑我们是否可以)?(我们不能预先设置堆栈帧)。

免责声明:这不是一个真正的答案,因为我没有直接解决RSP交换机问题,但它太长了,无法添加到评论中

根据我的经验,您应该只附加一次本机线程,并在它退出之前分离一次。如果不知道是否已附加,请使用以下代码:

jint rv = vm->GetEnv((void**)&env, JNI_VERSION_1_6);
if (rv == JNI_EDETACHED) {
    vm->AttachCurrentThread((void**)&env, 0);
}

首先,我建议您确保在创建任何关联的光纤之前只连接到线程一次,在每个本机线程退出之前只分离一次(或者如果本机线程没有终止,则根本不分离)。

我知道这并不能完全回答您的问题,但您可以尝试替换boost::context光纤(用C++实现)使用Java世界中的一些光纤实现。在这种情况下,它们通常被称为协程。这里的一些现有实现:您找到解决方案了吗?我正在尝试利用Boost.Coroutine,需要在这样一个例程中从JNI调用Java空间,这会导致很多失败。。。