Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
uses: actions/checkout@v4
with:
repository: ZettaScaleLabs/zenoh-flat-jni
ref: e4a8ed7a354f6f44ab1e44f70771298dc82c9c67
ref: dbb1f8c6509e333f49d1c03ecb84dcf07b7af7b8
path: zenoh-flat-jni

- name: Check out zenoh-flat
Expand Down
3 changes: 3 additions & 0 deletions zenoh-java/src/commonMain/kotlin/io/zenoh/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ import java.nio.file.Path
*
* A default configuration can be loaded using [Config.loadDefault].
*
* The native configuration a Config wraps is consumed by [Zenoh.open] (or [Zenoh.scout]); a Config that is
* never used is released by the garbage-collection backstop.
*
* Visit the [default configuration](https://github.com/eclipse-zenoh/zenoh/blob/main/DEFAULT_CONFIG.json5) for more
* information on the Zenoh config parameters.
*/
Expand Down
7 changes: 6 additions & 1 deletion zenoh-java/src/commonMain/kotlin/io/zenoh/Session.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ import java.util.concurrent.LinkedBlockingDeque
* Sessions are open upon creation and can be closed manually by calling [close]. Alternatively, the session will be
* automatically closed when used with Java's try-with-resources statement or its Kotlin counterpart, [use].
*
* Native resources held by a session (and by its declarations) that is simply forgotten are released by a
* garbage-collection backstop once the objects become unreachable; still, explicit [close] is recommended for
* deterministic release.
*
* For optimal performance and adherence to good practices, it is recommended to have only one running session, which
* is sufficient for most use cases. You should _never_ construct one session per publisher/subscriber, as this will
* significantly increase the size of your Zenoh network, while preventing potential locality-based optimizations.
Expand Down Expand Up @@ -96,7 +100,8 @@ class Session private constructor(private val config: Config) : AutoCloseable {
* Closing the session invalidates any attempt to perform a declaration or to perform an operation such as Put or Delete.
* Attempting to do so will result in a failure.
*
* However, any session declaration that was still alive and bound to the session previous to closing it, will still be alive.
* Every declaration still bound to the session (subscribers, queryables, publishers, queriers, …) is undeclared
* as part of closing it.
*/
override fun close() {
strongDeclarations.removeIf {
Expand Down
14 changes: 14 additions & 0 deletions zenoh-java/src/commonMain/kotlin/io/zenoh/bytes/ZBytes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ import io.zenoh.jni.bytes.ZBytes as JniZBytes
* encouraged to use any data format of their choice like JSON, protobuf,
* flatbuffers, etc.
*
* # Native memory lifecycle
*
* A ZBytes *created* from user data ([from]) is a plain value — it never
* holds native memory. A *received* ZBytes (a sample's payload or
* attachment, a query payload, a reply) wraps a native buffer that is
* freed automatically on the first [bytes] access (the bytes are copied
* out lazily, once). A received ZBytes whose content is **never read**
* keeps its native buffer allocated: unlike every other handle-owning
* class in this SDK, ZBytes is deliberately NOT covered by the
* garbage-collection backstop — payloads are the per-message hot path,
* and registering a GC cleaner per message measured −23% throughput at
* small payload sizes. In callback-based subscribers/queryables, access
* (or discard) payloads and attachments you care about; unread ones on
* dropped samples are the one place native memory can be retained.
*/
class ZBytes private constructor(
private var eager: ByteArray?,
Expand Down
4 changes: 3 additions & 1 deletion zenoh-java/src/commonMain/kotlin/io/zenoh/keyexpr/KeyExpr.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ import io.zenoh.query.Selector
* A [KeyExpr] is its validated string. A native instance exists ONLY behind a
* [Session.declareKeyExpr] result — the single case where zenoh attaches a wire
* declaration (a compact id replacing the string on the wire) worth carrying;
* such an instance should be [close]d (or `use`d) when no longer needed.
* such an instance should be [close]d (or `use`d) when no longer needed —
* the declaring session keeps a strong reference to it and undeclares it when
* the session closes, with a garbage-collection backstop after that.
* Every other [KeyExpr] — constructed via [tryFrom]/[autocanonize] or received
* with a sample — is a plain value: nothing to close, no native resource.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ import io.zenoh.session.SessionDeclaration
* that declared the token has Zenoh connectivity with the Zenoh application
* that monitors it.
*
* Liveliness tokens are automatically undeclared when dropped.
* A token whose last reference is dropped is undeclared by the garbage-collection backstop
* (non-deterministic — call [undeclare] or [close] to withdraw the liveliness promptly).
*/
class LivelinessToken internal constructor(private var token: io.zenoh.jni.liveliness.LivelinessToken?): SessionDeclaration, AutoCloseable {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ import kotlin.Throws
* A Zenoh Publisher.
*
* A publisher is automatically dropped when using it with the 'try-with-resources' statement (i.e. 'use' in Kotlin).
* The session from which it was declared will also keep a reference to it and undeclare it once the session is closed.
* The session keeps only a *weak* reference to it: a publisher whose last reference is dropped is undeclared by the
* garbage-collection backstop (non-deterministic — call [close] for prompt effect), and closing the session
* undeclares any publisher still reachable.
*
* In order to declare a publisher, [Session.declarePublisher] must be called.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import io.zenoh.session.SessionDeclaration
*
* Its main purpose is to keep the subscription active as long as it exists.
*
* The declaring session holds a *strong* reference to it: dropping your own reference does NOT stop the
* subscription — it stays active until [close] (or `undeclare`) is called or the session is closed, whichever
* comes first. Only after that does it become eligible for garbage collection.
*
* Example using the default [BlockingQueueHandler] handler:
*
* ```java
Expand Down
4 changes: 3 additions & 1 deletion zenoh-java/src/commonMain/kotlin/io/zenoh/query/Querier.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ import java.util.concurrent.LinkedBlockingDeque
/**
* A querier that allows to send queries to a [Queryable].
*
* Queriers are automatically undeclared when dropped.
* A querier whose last reference is dropped is undeclared by the garbage-collection backstop
* (non-deterministic — call `close` for prompt effect); closing the session undeclares any querier
* still reachable.
*
* Example:
* ```java
Expand Down
4 changes: 4 additions & 0 deletions zenoh-java/src/commonMain/kotlin/io/zenoh/query/Queryable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ import io.zenoh.session.SessionDeclaration
*
* Its main purpose is to keep the queryable active as long as it exists.
*
* The declaring session holds a *strong* reference to it: dropping your own reference does NOT stop the
* queryable — it stays active until [close] (or `undeclare`) is called or the session is closed, whichever
* comes first. Only after that does it become eligible for garbage collection.
*
* Example using the default [BlockingQueueHandler] handler:
* ```java
* try (Session session = Zenoh.open(config)) {
Expand Down
3 changes: 2 additions & 1 deletion zenoh-java/src/commonMain/kotlin/io/zenoh/scouting/Scout.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ import io.zenoh.handlers.Callback
* Scout for routers and/or peers.
*
* Scout spawns a task that periodically sends scout messages and waits for Hello replies.
* Drop the returned Scout to stop the scouting task.
* Call `stop` (or `close`) on the returned Scout to stop the scouting task; a Scout whose last
* reference is dropped is stopped by the garbage-collection backstop (non-deterministic).
*
* To launch a scout, use [io.zenoh.Zenoh.scout]:
*
Expand Down
Loading