Java nesnelerinin çoğunun, eşdeğer C++ nesneleri için gerçekten sarmalayıcı olduğu bir Java API'sı üzerinde çalışıyorum. Java nesneleri C++ nesneleri oluşturur ve artık gerekmediklerinde onları serbest bırakmaktan sorumludur. Bunun için kullanılacak en iyi desen hakkında merak ediyorum, ben iki olası seçenekleri görebilirsiniz:C++ Nesneleri sarma için en iyi JNI Kalıbı?
yerli kolu tutmak için statik bir yerel yöntem çağrısı ve son değişken kullanmak yapıcısındaki C++ nesne Construct.
public abstract class NativeBackedObject1 implements java.lang.AutoCloseable { protected final long _nativeHandle; protected final AtomicBoolean _nativeOwner; protected NativeBackedObject1(final long nativeHandle) { this._nativeHandle = nativeHandle; this._nativeOwner = new AtomicBoolean(true); } @Override public close() { if(_nativeOwner.copareAndSet(true, false)) { disposeInternal(); } } protected abstract void disposeInternal(); } public SomeFoo1 extends NativeBackendObject1 { public SomeFoo1() { super(newFoo()); } @Override protected final void disposeInternal() { //TODO: any local object specific cleanup disposeInternal(_nativeHandle); } private native static long newFoo(); private native disposeInternal(final long nativeHandle); }
- doğal kolu tutmak için bir örneği, doğal yöntem çağrısı olmayan bir son değişken kullanarak yapıcısında C++ nesnesi oluşturun.
public abstract class NativeBackedObject2 implements java.lang.AutoCloseable { protected long _nativeHandle; protected boolean _nativeOwner; protected NativeBackedObject2() { this._nativeHandle = 0; this._nativeOwner = true; } @Override public void close() { synchronized(this) { if(_nativeOwner && _nativeHandle != 0) { disposeInternal(); _nativeHandle = 0; _nativeOwner = false; } } } protected abstract void disposeInternal(); } public SomeFoo2 extends NativeBackendObject2 { public SomeFoo2() { super(); _nativeHandle = newFoo(); } @Override protected final void disposeInternal() { //TODO: any local object specific cleanup disposeInternal(_nativeHandle); } private native long newFoo(); private native disposeInternal(final long nativeHandle); }
anda
O (1) daha iyi bir yaklaşımdır düşünüyorum
, çünkü:- a. Bu,
_nativeHandle
'u immutable olarak ayarlayabileceğim anlamına gelir (final
). Dolayısıyla, eşzamanlı erişim veya beklenmedik değişiklikler hakkında endişelenmem gerekmiyor (kod, bu basit örneklerin aslında daha karmaşıktır). - b. Yapıcıdan dolayı,
NativeBackedObject
'un herhangi bir alt sınıfının (_nativeHandle
tarafından temsil edilen) kendi yerel nesnesinin sahibi olmadığı için tasarımda resmileştirildiğini ve bu sayede oluşturulmadığını resmileştirdim.
Yaklaşma (1) üzerinde (1) veya yaklaşımla ilgili herhangi bir sorun (1) var mıdır?
Ben de yaklaşmak için alternatif desen görebiliyordu(1), yaklaşımı diyelim (3):
public abstract class NativeBackedObject3 implements java.lang.AutoCloseable {
protected final long _nativeHandle;
protected final AtomicBoolean _nativeOwner;
protected NativeBackedObject3() {
this._nativeHandle = newInternal();
this._nativeOwner = new AtomicBoolean(true);
}
@Override
public close() {
if(_nativeOwner.copareAndSet(true, false)) {
disposeInternal();
}
}
protected abstract long newInternal();
protected abstract void disposeInternal();
}
public SomeFoo3 extends NativeBackendObject3 {
public SomeFoo3() {
super();
}
@Override
protected final void disposeInternal() {
//TODO: any local object specific cleanup
disposeInternal(_nativeHandle);
}
@Override
protected long newInternal() {
return newFoo();
};
private native long newFoo();
private native disposeInternal(final long nativeHandle);
}
avantajı (3) (1), ben geri hareket olmasıdır üzerinde Testler için alay yaratmaya yardımcı olabilecek bir varsayılan kurucu. Büyük dezavantaj da, artık ek paramları newFoo()
'a geçiremem.
Belki de kaçırdığım başka yaklaşımlar var mı? Öneriler hoş geldiniz ...
NativeBackedObjects ne tür bir yaşam döngüsüne sahip olur? –
Yaşam döngüsü, API tüketicisi tarafından manuel olarak yönetilecek, AutoCloseable özelliğini kullanabildim, böylece temizliği yönetmek için kaynakları kullanmayı deneyin. – adamretter
Herhangi bir multithreading yapacak mısınız? Ayrıca '_nativeOwner' AtomicBoolean'ınızı anlamaya çalışıyorum. Bu nesnenin yapıcısı tarafından oluşturulan "NativeBackedObject" adlı bir 'final' örneği değişkeni verildiğinde, sahiplik olarak tanımladığınız şeyi değiştiren ek kodunuz yoksa, bu Boolean için herhangi bir gereksinim görmüyorum. Mevcut “NativeBackedObject” öğesinin **, yerel kodunuzda "yeni" yoluyla aldığım, kendi yerel nesnesine ** referansı var. Mülkiyeti geçmek zorundasın, ve eğer mümkün olursa, bundan kaçınmalıyım. O & M kabusu olurdu. –