给定以下代码示例:
try (AutoClosable closable = new XXX()) {
o.method1(closable);
o.method2();
}Java模型允许HotSpot在closable.close()之前重新排序o.method2()吗?
我故意忽略了实现细节,比如method1是否捕获了可关闭的?在这个问题的第一部分。
我的具体用例是:
我有一个C库,可以概括为:
static char* value;
void capture(char* ptr){
value = ptr;
}
int len(void) {
return strlen(value);
}此本机库使用JNA包装。
interface CApi extends Library {
static {
Native.register("test.so", CApi.class)
}
void capture(Pointer s);
int test();
}我最初的客户端代码如下所示:
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!)。
try (AutoClosableMemory m = [...]) {
cApi.capture(m);
cApi.test();
}我能保证m.close()永远不会在cApi.test()之前被调用,并且m是强可达的吗?在这种情况下,m被底层的case捕获,但是java编译器无法知道它。
发布于 2017-10-14 10:50:14
理论上,JVM可以重新排序指令,但是方法的结果必须保持正确。HotSpot不理解本机代码,为了保证正确性,它从不围绕本机指令重新排序代码。
发布于 2017-10-13 17:45:23
对于一个线程,保证一切都以与代码相同的顺序运行(任何确实发生的重新排序都不会影响您的程序)。重新排序只会影响其他线程如何查看发生的情况。在您的问题中,只有一个线程,所以您的程序保证在cApi.test()之前调用m.close()。
https://stackoverflow.com/questions/46735264
复制相似问题