or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

functional-interfaces.mdindex.mdresource-management.mdtype-system.mdutility-classes.md

resource-management.mddocs/

0

# Resource Management

1

2

Resource management in Elasticsearch Core provides consistent lifecycle patterns for objects that require explicit cleanup. The system is built around reference counting and releasable interfaces, ensuring proper resource cleanup and preventing memory leaks in long-running applications.

3

4

## Capabilities

5

6

### RefCounted Interface

7

8

Reference counting interface for managing object lifecycles. Objects start with a reference count and are cleaned up when the count reaches zero.

9

10

```java { .api }

11

/**

12

* Interface for objects that support reference counting for lifecycle management

13

*/

14

public interface RefCounted {

15

/** Increment the reference count */

16

void incRef();

17

18

/** Try to increment reference count, returns false if already closed */

19

boolean tryIncRef();

20

21

/** Decrement reference count, closes object when count reaches zero */

22

boolean decRef();

23

24

/** Check if object still has active references */

25

boolean hasReferences();

26

27

/** Assert increment reference count (throws if closed) */

28

default void mustIncRef();

29

30

/** No-op RefCounted instance that is always referenced */

31

RefCounted ALWAYS_REFERENCED = new RefCounted() {

32

// Implementation details omitted for brevity

33

};

34

}

35

```

36

37

**Usage Examples:**

38

39

```java

40

import org.elasticsearch.core.RefCounted;

41

import org.elasticsearch.core.AbstractRefCounted;

42

43

// Create a ref-counted resource

44

RefCounted resource = AbstractRefCounted.of(() -> {

45

System.out.println("Resource cleaned up");

46

});

47

48

// Increment reference before sharing

49

resource.incRef();

50

shareResource(resource);

51

52

// Always decrement when done

53

resource.decRef(); // Will close when count reaches 0

54

```

55

56

### Releasable Interface

57

58

Simplified closeable interface that only throws RuntimeException, making it easier to use in functional contexts.

59

60

```java { .api }

61

/**

62

* A Closeable that can only throw a RuntimeException

63

*/

64

public interface Releasable extends Closeable {

65

/** Close the resource, only throws RuntimeException */

66

void close();

67

}

68

```

69

70

### AbstractRefCounted Class

71

72

Base implementation of RefCounted that provides thread-safe reference counting with customizable cleanup logic.

73

74

```java { .api }

75

/**

76

* Base RefCounted implementation with reference count starting at 1

77

*/

78

public abstract class AbstractRefCounted implements RefCounted {

79

/** Protected constructor for subclasses */

80

protected AbstractRefCounted();

81

82

/** Increment reference count */

83

public final void incRef();

84

85

/** Must increment reference count (throws if closed) */

86

public final void mustIncRef();

87

88

/** Try to increment reference count */

89

public final boolean tryIncRef();

90

91

/** Decrement reference count */

92

public final boolean decRef();

93

94

/** Check if references exist */

95

public final boolean hasReferences();

96

97

/** Get current reference count */

98

public final int refCount();

99

100

/** Abstract method for cleanup implementation */

101

protected abstract void closeInternal();

102

103

/** Factory method for simple cleanup actions */

104

public static AbstractRefCounted of(Runnable onClose);

105

106

/** Override for debugging access patterns */

107

protected void touch();

108

109

/** Handle already closed state */

110

protected void alreadyClosed();

111

112

/** Error message constant */

113

public static final String ALREADY_CLOSED_MESSAGE = "RefCounted is already closed";

114

115

/** Error message constant */

116

public static final String INVALID_DECREF_MESSAGE = "RefCounted decRef without incRef";

117

}

118

```

119

120

**Usage Examples:**

121

122

```java

123

// Custom RefCounted implementation

124

public class DatabaseConnection extends AbstractRefCounted {

125

private final Connection connection;

126

127

public DatabaseConnection(Connection connection) {

128

this.connection = connection;

129

}

130

131

@Override

132

protected void closeInternal() {

133

try {

134

connection.close();

135

} catch (SQLException e) {

136

throw new RuntimeException(e);

137

}

138

}

139

140

public ResultSet query(String sql) throws SQLException {

141

if (!hasReferences()) {

142

throw new IllegalStateException("Connection is closed");

143

}

144

return connection.prepareStatement(sql).executeQuery();

145

}

146

}

147

148

// Using the factory method

149

AbstractRefCounted fileResource = AbstractRefCounted.of(() -> {

150

try {

151

Files.deleteIfExists(tempFile);

152

} catch (IOException e) {

153

throw new RuntimeException(e);

154

}

155

});

156

```

157

158

### SimpleRefCounted Class

159

160

RefCounted implementation with no-op close behavior. It is the responsibility of the caller to run whatever release logic should be executed when decRef() returns true.

161

162

```java { .api }

163

/**

164

* RefCounted implementation with no-op close behavior

165

*/

166

public class SimpleRefCounted extends AbstractRefCounted {

167

/** No-op close implementation */

168

protected void closeInternal();

169

}

170

```

171

172

### ReleasableIterator Interface

173

174

Iterator that implements Releasable for proper resource cleanup during iteration.

175

176

```java { .api }

177

/**

178

* An iterator that implements Releasable for resource cleanup

179

*/

180

public interface ReleasableIterator<T> extends Releasable, Iterator<T> {

181

/** Create iterator with single element */

182

static <T extends Releasable> ReleasableIterator<T> single(T element);

183

184

/** Create empty iterator */

185

static <T extends Releasable> ReleasableIterator<T> empty();

186

}

187

```

188

189

### Releasables Utility

190

191

Utility methods for managing collections of Releasable objects with proper exception handling.

192

193

```java { .api }

194

/**

195

* Utility methods for managing Releasable objects

196

*/

197

public enum Releasables {

198

; // Utility enum with static methods only

199

200

/** Close multiple releasables, collecting exceptions */

201

public static void close(Iterable<? extends Releasable> releasables);

202

203

/** Close single releasable safely */

204

public static void close(@Nullable Releasable releasable);

205

206

/** Close multiple releasables safely */

207

public static void close(Releasable... releasables);

208

209

/** Close expecting no exceptions (throws AssertionError if exceptions occur) */

210

public static void closeExpectNoException(Releasable... releasables);

211

212

/** Close single releasable expecting no exceptions */

213

public static void closeExpectNoException(Releasable releasable);

214

215

/** Close while handling other exceptions */

216

public static void closeWhileHandlingException(Releasable... releasables);

217

218

/** Wrap multiple releasables into single releasable */

219

public static Releasable wrap(Iterable<? extends Releasable> releasables);

220

221

/** Wrap iterator of releasables */

222

public static Releasable wrap(Iterator<Releasable> releasables);

223

224

/** Wrap array of releasables */

225

public static Releasable wrap(Releasable... releasables);

226

227

/** Ensure releasable is only closed once */

228

public static Releasable releaseOnce(Releasable releasable);

229

230

/** Add assertion checking to releasable */

231

public static Releasable assertOnce(Releasable delegate);

232

}

233

```

234

235

**Usage Examples:**

236

237

```java

238

import org.elasticsearch.core.Releasables;

239

import org.elasticsearch.core.Releasable;

240

import java.util.List;

241

242

// Close multiple resources safely

243

List<Releasable> resources = Arrays.asList(resource1, resource2, resource3);

244

Releasables.close(resources);

245

246

// Wrap multiple resources for batch cleanup

247

Releasable batchResource = Releasables.wrap(resource1, resource2, resource3);

248

// Later: batchResource.close(); // Closes all wrapped resources

249

250

// Ensure single-close semantics

251

Releasable onceOnly = Releasables.releaseOnce(resource);

252

onceOnly.close(); // Works

253

onceOnly.close(); // Safe no-op

254

```