-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
java: create native resource management system (#1138)
Description: Adds the general-purpose capability for java objects to be associated with and manage native resources tied to the lifecycle of said object. Also introduces filter callbacks as the first use case for this system. Risk Level: Moderate Testing: Pending (#1139) Signed-off-by: Mike Schore <[email protected]> Signed-off-by: JP Simard <[email protected]>
- Loading branch information
Showing
8 changed files
with
210 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
mobile/library/java/src/io/envoyproxy/envoymobile/engine/EnvoyHTTPFilterCallbacks.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package io.envoyproxy.envoymobile.engine; | ||
|
||
public interface EnvoyHTTPFilterCallbacks { void resumeIteration(); } |
37 changes: 37 additions & 0 deletions
37
mobile/library/java/src/io/envoyproxy/envoymobile/engine/EnvoyHTTPFilterCallbacksImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package io.envoyproxy.envoymobile.engine; | ||
|
||
import io.envoyproxy.envoymobile.engine.EnvoyNativeResourceReleaser; | ||
import io.envoyproxy.envoymobile.engine.EnvoyNativeResourceWrapper; | ||
|
||
final class EnvoyHTTPFilterCallbacksImpl | ||
implements EnvoyHTTPFilterCallbacks, EnvoyNativeResourceWrapper { | ||
|
||
private static final EnvoyNativeResourceReleaser releaseCallbacks = (long handle) -> { | ||
callReleaseCallbacks(handle); | ||
}; | ||
|
||
private final long callbackHandle; | ||
|
||
/** | ||
* @param callbackHandle, native handle for callback execution. This must be eventually passed to | ||
`callReleaseCallbacks` to release underlying memory. | ||
*/ | ||
EnvoyHTTPFilterCallbacksImpl(long callbackHandle) { this.callbackHandle = callbackHandle; } | ||
|
||
static EnvoyHTTPFilterCallbacksImpl create(long callbackHandle) { | ||
final EnvoyHTTPFilterCallbacksImpl object = new EnvoyHTTPFilterCallbacksImpl(callbackHandle); | ||
EnvoyNativeResourceRegistry.globalRegister(object, callbackHandle, releaseCallbacks); | ||
return object; | ||
} | ||
|
||
public void resumeIteration() { callResumeIteration(callbackHandle, this); } | ||
|
||
/** | ||
* @param callbackHandle, native handle for callback execution. | ||
* @param object, pass this object so that the JNI retains it, preventing it from potentially | ||
* being concurrently garbage-collected while the native call is executing. | ||
*/ | ||
private native void callResumeIteration(long callbackHandle, EnvoyHTTPFilterCallbacksImpl object); | ||
|
||
private static native void callReleaseCallbacks(long callbackHandle); | ||
} |
58 changes: 58 additions & 0 deletions
58
mobile/library/java/src/io/envoyproxy/envoymobile/engine/EnvoyNativeMemoryRegistry.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package io.envoyproxy.envoymobile.engine; | ||
|
||
import java.lang.ref.PhantomReference; | ||
import java.lang.ref.ReferenceQueue; | ||
|
||
import io.envoyproxy.envoymobile.engine.EnvoyNativeResourceReleaser; | ||
import io.envoyproxy.envoymobile.engine.EnvoyNativeResourceWrapper; | ||
|
||
/** | ||
* Central class to manage releasing native resources when wrapper objects are flagged as | ||
* unreachable by the garbage collector. | ||
*/ | ||
public enum EnvoyNativeResourceRegistry { | ||
SINGLETON; | ||
|
||
private ReferenceQueue | ||
refQueue; // References are automatically enqueued when the gc flags them as unreachable. | ||
private Collection refMaintainer; // Maintains references in the object graph while we wait for | ||
// them to be enqueued. | ||
|
||
private class QueueThread extends Thread { | ||
public void run() { | ||
while (EnvoyPhantomRef releasable = (EnvoyPhantomRef)refQueue.remove()) { | ||
releasable.releaseResource(); | ||
refMaintainer.remove(releasable); | ||
} | ||
} | ||
} | ||
|
||
private class EnvoyPhantomRef extends PhantomReference<EnvoyNativeResourceWrapper> { | ||
private final EnvoyNativeResourceReleaser releaser; | ||
private final long nativeHandle; | ||
|
||
EnvoyPhantomRef(EnvoyNativeResourceWrapper owner, long nativeHandle, | ||
EnvoyNativeResourceReleaser releaser) { | ||
super(owner, refQueue); | ||
this.nativeHandle = nativeHandle; | ||
this.releaser = releaser; | ||
} | ||
|
||
releaseResource() { releaser.run(nativeHandle); } | ||
} | ||
|
||
/** | ||
* Register an EnvoyNativeResourceWrapper to schedule cleanup of its native resources when the | ||
* Java object is flagged for collection by the garbage collector. | ||
*/ | ||
public void register(EnvoyNativeResourceWrapper owner, long nativeHandle, | ||
EnvoyNativeResourceReleaser releaser) { | ||
EnvoyPhantomRef ref = new EnvoyPhantomRef(owner, nativeHandle, releaser); | ||
refMaintainer.add(ref); | ||
} | ||
|
||
public static void register(EnvoyNativeResourceWrapper owner, long nativeHandle, | ||
EnvoyNativeResourceReleaser releaser) { | ||
SINGLETON.register(owner, nativeHandle, releaser); | ||
} | ||
} |
84 changes: 84 additions & 0 deletions
84
mobile/library/java/src/io/envoyproxy/envoymobile/engine/EnvoyNativeResourceRegistry.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package io.envoyproxy.envoymobile.engine; | ||
|
||
import java.lang.ref.PhantomReference; | ||
import java.lang.ref.ReferenceQueue; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.Set; | ||
|
||
import io.envoyproxy.envoymobile.engine.EnvoyNativeResourceReleaser; | ||
import io.envoyproxy.envoymobile.engine.EnvoyNativeResourceWrapper; | ||
|
||
/** | ||
* Central class to manage releasing native resources when wrapper objects are flagged as | ||
* unreachable by the garbage collector. | ||
*/ | ||
public enum EnvoyNativeResourceRegistry { | ||
SINGLETON; | ||
|
||
// References are automatically enqueued when the gc flags them as unreachable. | ||
private ReferenceQueue refQueue; | ||
// Maintains references in the object graph while we wait for them to be enqueued. | ||
private Set refMaintainer; | ||
// Blocks on the reference queue and calls the releaser of queued references. | ||
private RefQueueThread refQueueThread; | ||
|
||
private class RefQueueThread extends Thread { | ||
public void run() { | ||
EnvoyPhantomRef ref; | ||
while (true) { | ||
try { | ||
ref = (EnvoyPhantomRef)refQueue.remove(); | ||
} catch (InterruptedException e) { | ||
continue; | ||
} | ||
|
||
ref.releaseResource(); | ||
refMaintainer.remove(ref); | ||
} | ||
} | ||
} | ||
|
||
private class EnvoyPhantomRef extends PhantomReference<EnvoyNativeResourceWrapper> { | ||
private final EnvoyNativeResourceReleaser releaser; | ||
private final long nativeHandle; | ||
|
||
EnvoyPhantomRef(EnvoyNativeResourceWrapper owner, long nativeHandle, | ||
EnvoyNativeResourceReleaser releaser) { | ||
super(owner, refQueue); | ||
this.nativeHandle = nativeHandle; | ||
this.releaser = releaser; | ||
refQueueThread = new RefQueueThread(); | ||
refMaintainer = new ConcurrentHashMap().newKeySet(); | ||
refQueueThread.start(); | ||
} | ||
|
||
void releaseResource() { releaser.release(nativeHandle); } | ||
} | ||
|
||
/** | ||
* Register an EnvoyNativeResourceWrapper to schedule cleanup of its native resources when the | ||
* Java object is flagged for collection by the garbage collector. | ||
* | ||
* @param owner, The object that has retained the native resource. | ||
* @param nativeHandle, An opaque identifier for the native resource. | ||
* @param releaser, A lambda that makes the native call to release the resource. | ||
*/ | ||
public void register(EnvoyNativeResourceWrapper owner, long nativeHandle, | ||
EnvoyNativeResourceReleaser releaser) { | ||
EnvoyPhantomRef ref = new EnvoyPhantomRef(owner, nativeHandle, releaser); | ||
refMaintainer.add(ref); | ||
} | ||
|
||
/** | ||
* Register an EnvoyNativeResourceWrapper to schedule cleanup of its native resources when the | ||
* Java object is flagged for collection by the garbage collector. | ||
* | ||
* @param owner, The object that has retained the native resource. | ||
* @param nativeHandle, An opaque identifier for the native resource. | ||
* @param releaser, A lambda that makes the native call to release the resource. | ||
*/ | ||
public static void globalRegister(EnvoyNativeResourceWrapper owner, long nativeHandle, | ||
EnvoyNativeResourceReleaser releaser) { | ||
SINGLETON.register(owner, nativeHandle, releaser); | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
mobile/library/java/src/io/envoyproxy/envoymobile/engine/EnvoyNativeResourceReleaser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package io.envoyproxy.envoymobile.engine; | ||
|
||
public interface EnvoyNativeResourceReleaser { | ||
|
||
/** | ||
* Release a native resource held by a Java object. | ||
* | ||
* @param @nativeHandle, JNI identifier for the native resource. | ||
*/ | ||
public void release(long nativeHandle); | ||
} |
8 changes: 8 additions & 0 deletions
8
mobile/library/java/src/io/envoyproxy/envoymobile/engine/EnvoyNativeResourceWrapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package io.envoyproxy.envoymobile.engine; | ||
|
||
/** | ||
* This interface exists solely to scope the types accepted by EnvoyNativeResourceRegistry. | ||
* | ||
* Implemented by objects that require a native resource to be tied to their lifecycle. | ||
*/ | ||
interface EnvoyNativeResourceWrapper {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters