prevent reference cycles between Java and native objects

This commit is contained in:
Julian Winkler
2024-07-26 21:47:08 +02:00
parent 45801d8f17
commit e3c0931714
30 changed files with 257 additions and 181 deletions

View File

@@ -370,6 +370,8 @@ public class Activity extends ContextThemeWrapper implements Window.Callback {
@Override
public void run() {
nativeFinish(getWindow().native_window);
getWindow().setContentView(null);
window = null;
}
});
}

View File

@@ -1596,6 +1596,18 @@ public final class Bitmap {
}
}
@Override
@SuppressWarnings("deprecation")
protected void finalize() throws Throwable {
try {
super.finalize();
} finally {
if (!isRecycled()) {
recycle();
}
}
}
/**
* internal ATL method to create or get a GdkTexture for the pixbuf
* @return pointer to the GdkTexture

View File

@@ -19,6 +19,19 @@ public class Canvas {
this.widget = widget;
}
@Override
@SuppressWarnings("deprecation")
protected void finalize() throws Throwable {
try {
super.finalize();
} finally {
if (skia_canvas != 0) {
native_destroy_canvas(skia_canvas);
skia_canvas = 0;
}
}
}
// FIXME: are these _needed_ ?
public int save() {
@@ -444,4 +457,5 @@ public class Canvas {
private static native void native_rotate(long skia_canvas, long widget, float angle);
private static native void native_rotate_and_translate(long skia_canvas, long widget, float angle, float tx, float ty);
private static native void native_drawPath(long skia_canvas, long path, long skia_paint);
private static native void native_destroy_canvas(long skia_canvas);
}

View File

@@ -18,6 +18,7 @@ public class MediaCodec {
private long native_codec;
private boolean outputFormatSet = false;
private MediaFormat mediaFormat;
private boolean isReleased = false;
private Queue<Integer> freeOutputBuffers;
private Queue<Integer> queuedInputBuffers;
@@ -148,6 +149,19 @@ public class MediaCodec {
public void release() {
System.out.println("MediaCodec.release(): codecName=" + codecName);
native_release(native_codec);
isReleased = true;
}
@Override
@SuppressWarnings("deprecation")
protected void finalize() throws Throwable {
try {
super.finalize();
} finally {
if (!isReleased) {
release();
}
}
}
private native long native_constructor(String codecName);

View File

@@ -616,7 +616,7 @@ public class View implements Drawable.Callback {
}
public interface OnLongClickListener {
// TODO
public boolean onLongClick(View v);
}
public interface OnHoverListener {
@@ -964,12 +964,25 @@ public class View implements Drawable.Callback {
this.gravity = gravity;
}
private OnTouchListener on_touch_listener = null;
public boolean onTouchEvent(MotionEvent event) {
return false;
if (on_touch_listener != null)
return on_touch_listener.onTouch(this, event);
else
return false;
}
public native void setOnTouchListener(OnTouchListener l);
public native void setOnClickListener(OnClickListener l);
public void setOnTouchListener(OnTouchListener l) {
nativeSetOnTouchListener(widget);
on_touch_listener = l;
}
protected native void nativeSetOnTouchListener(long widget);
private OnClickListener on_click_listener = null;
public void setOnClickListener(OnClickListener l) {
nativeSetOnClickListener(widget);
on_click_listener = l;
}
protected native void nativeSetOnClickListener(long widget);
public /*native*/ void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {}
public native final int getWidth();
public native final int getHeight();
@@ -1200,7 +1213,18 @@ public class View implements Drawable.Callback {
return null;
}
public native void setOnLongClickListener(OnLongClickListener listener);
private OnLongClickListener on_long_click_listener = null;
public boolean performLongClick(float x, float y) {
if (on_long_click_listener != null) {
return on_long_click_listener.onLongClick(this);
}
return false;
}
public void setOnLongClickListener(OnLongClickListener listener) {
nativeSetOnLongClickListener(widget);
on_long_click_listener = listener;
}
protected native void nativeSetOnLongClickListener(long widget);
public void setLongClickable(boolean longClickable) {}
@@ -1398,6 +1422,7 @@ public class View implements Drawable.Callback {
public boolean isInEditMode() {return false;}
@Override
@SuppressWarnings("deprecation")
protected void finalize() throws Throwable {
try {
native_destructor(widget);
@@ -1504,7 +1529,12 @@ public class View implements Drawable.Callback {
public void setDuplicateParentStateEnabled(boolean enabled) {}
public boolean performClick() {
return false;
if (on_click_listener != null) {
on_click_listener.onClick(this);
return true;
} else {
return false;
}
}
public void playSoundEffect(int soundConstant) {}
@@ -1662,6 +1692,9 @@ public class View implements Drawable.Callback {
protected void onAttachedToWindow () {
attachedToWindow = true;
}
protected void onDetachedFromWindow() {
attachedToWindow = false;
}
public void setLayerType(int layerType, Paint paint) {}

View File

@@ -91,6 +91,8 @@ public class ViewGroup extends View implements ViewParent, ViewManager {
child.parent = null;
children.remove(child);
native_removeView(widget, child.widget);
if (isAttachedToWindow())
child.onDetachedFromWindow();
if (onHierarchyChangeListener != null) {
onHierarchyChangeListener.onChildViewRemoved(this, child);
}
@@ -114,6 +116,8 @@ public class ViewGroup extends View implements ViewParent, ViewManager {
child.parent = null;
it.remove();
native_removeView(widget, child.widget);
if (isAttachedToWindow())
child.onDetachedFromWindow();
if (onHierarchyChangeListener != null) {
onHierarchyChangeListener.onChildViewRemoved(this, child);
}
@@ -317,6 +321,14 @@ public class ViewGroup extends View implements ViewParent, ViewManager {
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
for (View child: children) {
child.onDetachedFromWindow();
}
}
protected boolean isChildrenDrawingOrderEnabled() { return false; }
@Override

View File

@@ -46,9 +46,16 @@ public class Window {
}
public void setContentView(View view) {
if (contentView != view) {
if (contentView != null)
contentView.onDetachedFromWindow();
if (view != null)
view.onAttachedToWindow();
}
contentView = view;
view.onAttachedToWindow();
set_widget_as_root(native_window, view.widget);
if (view != null) {
set_widget_as_root(native_window, view.widget);
}
}
public View getDecorView() {

View File

@@ -24,7 +24,8 @@ public class Button extends TextView {
@Override
protected native long native_constructor(Context context, AttributeSet attrs);
public native final void native_setText(long widget, String text);
protected native void native_setOnClickListener(long widget, OnClickListener l);
@Override
protected native void nativeSetOnClickListener(long widget);
@Override
public void setText(CharSequence text) {
@@ -37,11 +38,6 @@ public class Button extends TextView {
@Override
public void setTextSize(float size) {}
@Override
public void setOnClickListener(final OnClickListener l) {
native_setOnClickListener(widget, l);
}
@Override
public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) {}

View File

@@ -23,11 +23,7 @@ public class ImageButton extends ImageView {
protected native void native_setPixbuf(long widget, long pixbuf);
@Override
protected native void native_setDrawable(long widget, long paintable);
protected native void native_setOnClickListener(long widget, OnClickListener l);
@Override
public void setOnClickListener(final OnClickListener l) {
native_setOnClickListener(widget, l);
}
protected native void nativeSetOnClickListener(long widget);
}

View File

@@ -169,12 +169,22 @@ public class TextView extends View {
protected native void native_setCompoundDrawables(long widget, long left, long top, long right, long bottom);
// just to prevent garbage collection while native side uses it
private Drawable drawableLeft = null;
private Drawable drawableTop = null;
private Drawable drawableRight = null;
private Drawable drawableBottom = null;
public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) {
native_setCompoundDrawables(widget,
left != null ? left.paintable : 0,
top != null ? top.paintable : 0,
right != null ? right.paintable : 0,
bottom != null ? bottom.paintable : 0);
drawableLeft = left;
drawableTop = top;
drawableRight = right;
drawableBottom = bottom;
}
public void setAllCaps(boolean allCaps) {}