- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
根据我作为 C++/Java/Android 开发人员的经验,我了解到终结器几乎总是一个坏主意,唯一的异常(exception)是管理 Java 调用 C/C++ 代码所需的“本地对等”对象通过 JNI。
我知道 JNI: Properly manage the lifetime of a java object question ,但这个问题解决了原因 无论如何都不要使用终结器,也不要用于 native 同行 .因此,这是对上述问题中答案的反驳的问题/讨论。
约书亚·布洛赫 (Joshua Bloch) 在他的 Effective Java 中明确地将此案例列为他关于不使用终结器的著名建议的异常(exception):
A second legitimate use of finalizers concerns objects with native peers. A native peer is a native object to which a normal object delegates via native methods. Because a native peer is not a normal object, the garbage collector doesn't know about it and can’t reclaim it when its Java peer is reclaimed. A finalizer is an appropriate vehicle for performing this task, assuming the native peer holds no critical resources. If the native peer holds resources that must be terminated promptly, the class should have an explicit termination method, as described above. The termination method should do whatever is required to free the critical resource. The termination method can be a native method, or it can invoke one.
java.lang.ref.PhantomReference
反而。
class BinaryPoly {
long mNativeHandle; // holds a c++ raw pointer
private BinaryPoly(long nativeHandle) {
mNativeHandle = nativeHandle;
}
private static native long nativeMultiply(long xCppPtr, long yCppPtr);
BinaryPoly multiply(BinaryPoly other) {
return new BinaryPoly ( nativeMultiply(mNativeHandle, other.mNativeHandler) );
}
// …
static native void nativeDelete (long cppPtr);
protected void finalize() {
nativeDelete(mNativeHandle);
}
}
在 java 类保存对在终结器方法中被删除的 native 对等点的引用的情况下,Bloch 列出了这种方法的缺点。
If two objects become unreachable, the finalizers actually run in arbitrary order, that includes the case when two objects who point to each others become unreachable at the same time they can be finalized in the wrong order, meaning that the second one to be finalized actually tries to access an object that’s already been finalized. [...] As a result of that you can get dangling pointers and see deallocated c++ objects [...]
class SomeClass {
BinaryPoly mMyBinaryPoly:
…
// DEFINITELY DON’T DO THIS WITH CURRENT BinaryPoly!
protected void finalize() {
Log.v(“BPC”, “Dropped + … + myBinaryPoly.toString());
}
}
好的,但是如果 myBinaryPoly 是一个纯 Java 对象,这不是真的吗?据我了解,问题来自在其所有者的终结器中操作可能已终结的对象。如果我们只使用对象的终结器来删除它自己的私有(private)本地对等点而不做其他任何事情,我们应该没问题,对吧?
By Java rules, but not currently on Android:
Object x’s finalizer may be invoked while one of x’s methods is still running, and accessing the native object.
multiply()
显示编译为以解释这一点:
BinaryPoly multiply(BinaryPoly other) {
long tmpx = this.mNativeHandle; // last use of “this”
long tmpy = other.mNativeHandle; // last use of other
BinaryPoly result = new BinaryPoly();
// GC happens here. “this” and “other” can be reclaimed and finalized.
// tmpx and tmpy are still needed. But finalizer can delete tmpx and tmpy here!
result.mNativeHandle = nativeMultiply(tmpx, tmpy)
return result;
}
这太可怕了,我实际上松了一口气,这不会发生在 android 上,因为我理解的是
this
和
other
在它们超出范围之前收集垃圾!考虑到
this
,这就更奇怪了。是调用该方法的对象,即
other
是方法的参数,因此它们都应该已经在调用方法的范围内“处于 Activity 状态”。
this
上调用一些虚拟方法。和
other
(丑!),或者将它们传递给本地方法(然后我们可以在其中检索
mNativeHandle
并对其进行操作)。等等...
this
默认情况下已经是 native 方法的参数之一!
JNIEXPORT void JNICALL Java_package_BinaryPoly_multiply
(JNIEnv* env, jobject thiz, jlong xPtr, jlong yPtr) {}
怎么可以
this
可能被垃圾收集?
“For this to work correctly, if you run an application that allocates lots of native memory and relatively little java memory it may actually not be the case that the garbage collector runs promptly enough to actually invoke finalizers [...] so you actually may have to invoke System.gc() and System.runFinalization() occasionally, which is tricky to do [...]”
[...] Sometimes finalizers actually extend the lifetime of the java object for another garbage collection cycle, which means for generational garbage collectors they may actually cause it to survive into the old generation and the lifetime may be greatly extended as a result of just having a finalizer.
最佳答案
finalize
和其他使用对象生命周期知识的方法有一些细微差别:
volatile
的一家商店在每个方法结束时 + 阅读相同 volatile
在终结器中。 keepAlive
实现)。 nativeMultiply
是 static
,因此 this
可能会被垃圾收集。 Reference#reachabilityFence
来自 Java 9+。 finalize
和
PhantomReferences
是后者让您可以更好地控制最终确定的各个方面:
ReferenceQueues
)。 B
必须在 A
时保持 Activity 状态最终确定为 PhantomReference
的字段至 A
; PhantomRefereces
强可达,直到它们被 GC 入队。 关于java - 对于 native 对等对象生命周期管理,是否真的应该避免 Java 终结器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44095247/
我有一个 if 语句,如下所示 if (not(fullpath.lower().endswith(".pdf")) or not (fullpath.lower().endswith(tup
然而,在 PHP 中,可以: only appears if $foo is true. only appears if $foo is false. 在 Javascript 中,能否在一个脚
XML有很多好处。它既是机器可读的,也是人类可读的,它具有标准化的格式,并且用途广泛。 它也有一些缺点。它是冗长的,不是传输大量数据的非常有效的方法。 XML最有用的方面之一是模式语言。使用模式,您可
由于长期使用 SQL2000,我并没有真正深入了解公用表表达式。 我给出的答案here (#4025380)和 here (#4018793)违背了潮流,因为他们没有使用 CTE。 我很欣赏它们对于递
我有一个应用程序: void deleteObj(id){ MyObj obj = getObjById(id); if (obj == null) { throw n
我的代码如下。可能我以类似的方式多次使用它,即简单地说,我正在以这种方式管理 session 和事务: List users= null; try{ sess
在开发J2EE Web应用程序时,我通常会按以下方式组织我的包结构 com.jameselsey.. 控制器-控制器/操作转到此处 服务-事务服务类,由控制器调用 域-应用程序使用的我的域类/对象 D
这更多是出于好奇而不是任何重要问题,但我只是想知道 memmove 中的以下片段文档: Copying takes place as if an intermediate buffer were us
路径压缩涉及将根指定为路径上每个节点的新父节点——这可能会降低根的等级,并可能降低路径上所有节点的等级。有办法解决这个问题吗?有必要处理这个吗?或者,也许可以将等级视为树高的上限而不是确切的高度? 谢
我有两个类,A 和 B。A 是 B 的父类,我有一个函数接收指向 A 类型类的指针,检查它是否也是 B 类型,如果是将调用另一个函数,该函数接受一个指向类型 B 的类的指针。当函数调用另一个函数时,我
有没有办法让 valgrind 使用多个处理器? 我正在使用 valgrind 的 callgrind 进行一些瓶颈分析,并注意到我的应用程序中的资源使用行为与在 valgrind/callgrind
假设我们要使用 ReaderT [(a,b)]超过 Maybe monad,然后我们想在列表中进行查找。 现在,一个简单且不常见的方法是: 第一种可能性 find a = ReaderT (looku
我的代码似乎有问题。我需要说的是: if ( $('html').attr('lang').val() == 'fr-FR' ) { // do this } else { // do
根据this文章(2018 年 4 月)AKS 在可用性集中运行时能够跨故障域智能放置 Pod,但尚不考虑更新域。很快就会使用更新域将 Pod 放入 AKS 中吗? 最佳答案 当您设置集群时,它已经自
course | section | type comart2 : bsit201 : lec comart2 :
我正在开发自己的 SDK,而这又依赖于某些第 3 方 SDK。例如 - OkHttp。 我应该将 OkHttp 添加到我的 build.gradle 中,还是让我的 SDK 用户包含它?在这种情况下,
随着 Rust 越来越充实,我对它的兴趣开始激起。我喜欢它支持代数数据类型,尤其是那些匹配的事实,但是对其他功能习语有什么想法吗? 例如标准库中是否有标准过滤器/映射/归约函数的集合,更重要的是,您能
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 9 年前。 Improve
我一直在研究 PHP 中的对象。我见过的所有示例甚至在它们自己的对象上都使用了对象构造函数。 PHP 会强制您这样做吗?如果是,为什么? 例如: firstname = $firstname;
...比关联数组? 关联数组会占用更多内存吗? $arr = array(1, 1, 1); $arr[10] = 1; $arr[] = 1; // <- index is 11; does the
我是一名优秀的程序员,十分优秀!