首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JMM保证在具有资源的尝试中重新排序& JNI调用。

JMM保证在具有资源的尝试中重新排序& JNI调用。
EN

Stack Overflow用户
提问于 2017-10-13 17:37:44
回答 2查看 96关注 0票数 2

给定以下代码示例:

代码语言:javascript
复制
 try (AutoClosable closable = new XXX()) {
      o.method1(closable);  
      o.method2();
 }

Java模型允许HotSpot在closable.close()之前重新排序o.method2()吗?

我故意忽略了实现细节,比如method1是否捕获了可关闭的?在这个问题的第一部分。

我的具体用例是:

我有一个C库,可以概括为:

代码语言:javascript
复制
static char* value;

void capture(char* ptr){
        value = ptr;
}

int len(void) {
    return strlen(value);
}

此本机库使用JNA包装。

代码语言:javascript
复制
interface CApi extends Library {

 static {
   Native.register("test.so", CApi.class)
 }

  void capture(Pointer s);
  int test();
}

我最初的客户端代码如下所示:

代码语言:javascript
复制
cApi = Native.loadLibrary("test.so", CApi.class);


byte[] data = Native.toByteArray("foo");
Memory m = new Memory(data.length + 1);
m.write(0, data, 0, data.length);
m.setByte(data.length, (byte)0);

cApi.capture(m);
System.out.print(cApi.len());

这个第一个版本的问题是,m是从Java分配的,并且这个内存的生命周期与m的强可达性有关。一旦m和内存将在GC启动时释放(JNA依赖finalize来释放本机内存),capture(m)就不再是强可访问的了。

为了防止这种情况,我建议将JNA的Memory子类引入一个AutoClosableMemory。这样做的想法是,使用带资源的尝试结构可以清楚地表明资源在此范围内是可强访问的。好处是我们可以释放本地内存,而不是等待GC (嘿,这是RAII!)。

代码语言:javascript
复制
try (AutoClosableMemory m = [...]) {
  cApi.capture(m);
  cApi.test();
}

我能保证m.close()永远不会在cApi.test()之前被调用,并且m是强可达的吗?在这种情况下,m被底层的case捕获,但是java编译器无法知道它。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-10-14 10:50:14

理论上,JVM可以重新排序指令,但是方法的结果必须保持正确。HotSpot不理解本机代码,为了保证正确性,它从不围绕本机指令重新排序代码。

票数 4
EN

Stack Overflow用户

发布于 2017-10-13 17:45:23

对于一个线程,保证一切都以与代码相同的顺序运行(任何确实发生的重新排序都不会影响您的程序)。重新排序只会影响其他线程如何查看发生的情况。在您的问题中,只有一个线程,所以您的程序保证在cApi.test()之前调用m.close()

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46735264

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档