- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等) - java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等) - javax/ 4个模块 (net/crypto/security/sql) - org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http) - dalvik/ 1个模块 (system) - ~3053个类/接口,方法签名完全对齐Android SDK - 桌面跨平台运行 (Windows/macOS/Linux) - 修复所有导入错误和Python关键字冲突
386 lines
11 KiB
Python
386 lines
11 KiB
Python
"""
|
|
Java java.lang.ref reference APIs implemented in Python.
|
|
java.lang.ref package - Reference, ReferenceQueue, SoftReference, WeakReference, PhantomReference, Finalizer.
|
|
Wraps Python weakref module.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from .._core import Stub, AndroidOnlyError
|
|
import weakref as _weakref
|
|
import threading as _threading
|
|
import gc as _gc
|
|
|
|
__all__ = [
|
|
"Reference", "SoftReference", "WeakReference", "PhantomReference",
|
|
"ReferenceQueue", "Finalizer", "FinalizerReference", "FinalizationWatchdog",
|
|
]
|
|
|
|
|
|
# ============================================================
|
|
# ReferenceQueue
|
|
# ============================================================
|
|
|
|
class ReferenceQueue(Stub):
|
|
"""
|
|
java.lang.ref.ReferenceQueue
|
|
A queue that References are appended to when they are enqueued.
|
|
"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._queue: list = []
|
|
self._lock = _threading.Lock()
|
|
self._cond = _threading.Condition(self._lock)
|
|
|
|
def poll(self):
|
|
"""
|
|
Polls to see if a reference object is available.
|
|
Returns the reference if available, None otherwise.
|
|
"""
|
|
with self._lock:
|
|
if self._queue:
|
|
return self._queue.pop(0)
|
|
return None
|
|
|
|
def remove(self, timeout: int = 0):
|
|
"""
|
|
Removes the next reference object from this queue, blocking until one is available
|
|
or the timeout expires.
|
|
Args:
|
|
timeout: timeout in milliseconds (0 = indefinite)
|
|
Returns:
|
|
The reference, or None if timeout expired.
|
|
"""
|
|
with self._lock:
|
|
if self._queue:
|
|
return self._queue.pop(0)
|
|
if timeout == 0:
|
|
self._cond.wait()
|
|
if self._queue:
|
|
return self._queue.pop(0)
|
|
return None
|
|
else:
|
|
self._cond.wait(timeout / 1000.0)
|
|
if self._queue:
|
|
return self._queue.pop(0)
|
|
return None
|
|
|
|
def enqueue(self, ref: "Reference") -> bool:
|
|
"""
|
|
Enqueues a reference onto this queue.
|
|
Returns True if successful.
|
|
"""
|
|
with self._lock:
|
|
self._queue.append(ref)
|
|
self._cond.notify()
|
|
return True
|
|
|
|
def __len__(self):
|
|
return len(self._queue)
|
|
|
|
|
|
# ============================================================
|
|
# Reference (abstract base)
|
|
# ============================================================
|
|
|
|
class Reference(Stub):
|
|
"""
|
|
java.lang.ref.Reference
|
|
Abstract base class for reference objects.
|
|
"""
|
|
|
|
def __init__(self, referent=None, queue: ReferenceQueue = None):
|
|
super().__init__()
|
|
self._referent = referent
|
|
self._queue = queue
|
|
self._enqueued = False
|
|
# Underlying weakref to track referent lifetime
|
|
self._weak = None
|
|
if referent is not None:
|
|
self._weak = _weakref.ref(
|
|
referent,
|
|
self._on_referent_collected
|
|
)
|
|
|
|
def _on_referent_collected(self, weakref_obj):
|
|
"""Called when the referent is garbage collected."""
|
|
if self._queue is not None and not self._enqueued:
|
|
self._enqueued = True
|
|
self._queue.enqueue(self)
|
|
|
|
def get(self):
|
|
"""
|
|
Returns this reference object's referent.
|
|
If the referent has been garbage collected, returns None.
|
|
"""
|
|
if self._weak is not None:
|
|
return self._weak()
|
|
return self._referent
|
|
|
|
def clear(self):
|
|
"""Clears this reference object."""
|
|
self._referent = None
|
|
if self._weak is not None:
|
|
self._weak = None
|
|
|
|
def isEnqueued(self) -> bool:
|
|
"""Returns whether this reference object has been enqueued."""
|
|
return self._enqueued
|
|
|
|
def enqueue(self) -> bool:
|
|
"""Enqueues this reference object."""
|
|
if self._queue is not None and not self._enqueued:
|
|
self._enqueued = True
|
|
return self._queue.enqueue(self)
|
|
return False
|
|
|
|
def clone(self):
|
|
"""Creates a shallow copy of this reference."""
|
|
return self.__class__(self.get(), self._queue)
|
|
|
|
def toString(self) -> str:
|
|
return f"{self.__class__.__name__}@{hex(id(self))}[referent={self.get()}]"
|
|
|
|
def equals(self, other) -> bool:
|
|
if not isinstance(other, Reference):
|
|
return False
|
|
return self.get() is other.get()
|
|
|
|
def hashCode(self) -> int:
|
|
r = self.get()
|
|
return hash(r) & 0x7FFFFFFF if r is not None else 0
|
|
|
|
|
|
# ============================================================
|
|
# SoftReference
|
|
# ============================================================
|
|
|
|
class SoftReference(Reference):
|
|
"""
|
|
java.lang.ref.SoftReference
|
|
Soft reference objects, cleared at the discretion of the GC.
|
|
"""
|
|
|
|
def __init__(self, referent=None, queue: ReferenceQueue = None):
|
|
super().__init__(referent, queue)
|
|
self._clock = 0
|
|
|
|
def get(self):
|
|
"""Returns the referent; on desktop, soft references are more resilient."""
|
|
return super().get()
|
|
|
|
def enqueue(self) -> bool:
|
|
return super().enqueue()
|
|
|
|
def clear(self):
|
|
super().clear()
|
|
|
|
def toString(self) -> str:
|
|
return f"SoftReference@{hex(id(self))}[referent={self.get()}]"
|
|
|
|
|
|
# ============================================================
|
|
# WeakReference
|
|
# ============================================================
|
|
|
|
class WeakReference(Reference):
|
|
"""
|
|
java.lang.ref.WeakReference
|
|
Weak reference objects, cleared automatically by the GC.
|
|
"""
|
|
|
|
def __init__(self, referent=None, queue: ReferenceQueue = None):
|
|
super().__init__(referent, queue)
|
|
|
|
def toString(self) -> str:
|
|
return f"WeakReference@{hex(id(self))}[referent={self.get()}]"
|
|
|
|
|
|
# ============================================================
|
|
# PhantomReference
|
|
# ============================================================
|
|
|
|
class PhantomReference(Reference):
|
|
"""
|
|
java.lang.ref.PhantomReference
|
|
Phantom reference objects. get() always returns None.
|
|
"""
|
|
|
|
def __init__(self, referent=None, queue: ReferenceQueue = None):
|
|
super().__init__(referent, queue)
|
|
|
|
def get(self):
|
|
"""
|
|
Phantom references always return None.
|
|
The referent is phantom-reachable and thus not accessible.
|
|
"""
|
|
return None
|
|
|
|
def toString(self) -> str:
|
|
return f"PhantomReference@{hex(id(self))}[referent=phantom]"
|
|
|
|
|
|
# ============================================================
|
|
# FinalizerReference
|
|
# ============================================================
|
|
|
|
class FinalizerReference(Reference):
|
|
"""
|
|
java.lang.ref.FinalizerReference
|
|
Represents a finalizer reference used by the VM's finalization system.
|
|
"""
|
|
|
|
def __init__(self, referent=None, queue: ReferenceQueue = None):
|
|
super().__init__(referent, queue)
|
|
self._finalized = False
|
|
self._finalize_method = None
|
|
if referent is not None and hasattr(referent, "finalize"):
|
|
self._finalize_method = getattr(referent, "finalize", None)
|
|
|
|
def finalize(self):
|
|
"""Invokes the referent's finalize method if it exists."""
|
|
if not self._finalized and self._finalize_method is not None:
|
|
try:
|
|
self._finalize_method()
|
|
except Exception:
|
|
pass
|
|
finally:
|
|
self._finalized = True
|
|
|
|
def isFinalized(self) -> bool:
|
|
return self._finalized
|
|
|
|
def toString(self) -> str:
|
|
return f"FinalizerReference@{hex(id(self))}[finalized={self._finalized}]"
|
|
|
|
|
|
# ============================================================
|
|
# FinalizationWatchdog
|
|
# ============================================================
|
|
|
|
class FinalizationWatchdog(Stub):
|
|
"""
|
|
java.lang.ref.FinalizationWatchdog
|
|
A watchdog thread that ensures finalizations proceed.
|
|
Desktop stub implementation.
|
|
"""
|
|
|
|
_instance = None
|
|
_running = False
|
|
_thread = None
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._timeout = 10000 # 10 seconds
|
|
|
|
@classmethod
|
|
def getInstance(cls):
|
|
if cls._instance is None:
|
|
cls._instance = FinalizationWatchdog()
|
|
return cls._instance
|
|
|
|
def start(self):
|
|
"""Starts the watchdog thread."""
|
|
if not self._running:
|
|
self._running = True
|
|
self._thread = _threading.Thread(target=self._run, daemon=True)
|
|
self._thread.start()
|
|
|
|
def stop(self):
|
|
"""Stops the watchdog thread."""
|
|
self._running = False
|
|
|
|
def _run(self):
|
|
"""Watchdog loop."""
|
|
while self._running:
|
|
_gc.collect()
|
|
import time
|
|
time.sleep(1)
|
|
|
|
def setEnabled(self, enabled: bool):
|
|
if enabled:
|
|
self.start()
|
|
else:
|
|
self.stop()
|
|
|
|
def toString(self) -> str:
|
|
return f"FinalizationWatchdog@{hex(id(self))}[running={self._running}]"
|
|
|
|
def equals(self, other) -> bool:
|
|
return self is other
|
|
|
|
def hashCode(self) -> int:
|
|
return hash(self) & 0x7FFFFFFF
|
|
|
|
|
|
# ============================================================
|
|
# Finalizer
|
|
# ============================================================
|
|
|
|
class Finalizer(Stub):
|
|
"""
|
|
java.lang.ref.Finalizer
|
|
Manages object finalization. Provides methods to run finalization.
|
|
"""
|
|
|
|
_instance = None
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
@classmethod
|
|
def runFinalization(cls):
|
|
"""
|
|
Runs the finalization methods of any objects pending finalization.
|
|
Equivalent to calling System.runFinalization().
|
|
"""
|
|
_gc.collect()
|
|
for obj in _gc.get_objects():
|
|
if hasattr(obj, "finalize"):
|
|
try:
|
|
obj.finalize()
|
|
except Exception:
|
|
pass
|
|
|
|
@classmethod
|
|
def runFinalizersOnExit(cls, value: bool):
|
|
"""
|
|
Sets whether finalization is enabled on exit.
|
|
Deprecated in Java. Desktop stub.
|
|
"""
|
|
if value:
|
|
import atexit
|
|
atexit.register(cls._finalize_all)
|
|
|
|
@classmethod
|
|
def _finalize_all(cls):
|
|
"""Finalize all objects on exit."""
|
|
for obj in _gc.get_objects():
|
|
if hasattr(obj, "finalize"):
|
|
try:
|
|
obj.finalize()
|
|
except Exception:
|
|
pass
|
|
|
|
@classmethod
|
|
def finalizeAllEnqueued(cls):
|
|
"""
|
|
Finalizes all objects that have been enqueued for finalization.
|
|
"""
|
|
_gc.collect()
|
|
for obj in _gc.get_objects():
|
|
if hasattr(obj, "finalize"):
|
|
try:
|
|
obj.finalize()
|
|
except Exception:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return f"Finalizer@{hex(id(self))}"
|
|
|
|
def equals(self, other) -> bool:
|
|
return self is other
|
|
|
|
def hashCode(self) -> int:
|
|
return hash(self) & 0x7FFFFFFF |