> For the complete documentation index, see [llms.txt](https://docs.xplatform.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.xplatform.com/talon/developing-applications/authoring-user-code/message-processing/processing-messages/handling-messages/coding-for-zero-garbage/xstrings.md).

# XStrings

XStrings provide a zero garbage alternative to Java Strings for ultra-low-latency applications. XStrings are mutable, string-like objects that can be pooled and preallocated so that string handling neither allocates nor promotes during message processing.

## Overview

An `XString` is a mutable, zero garbage alternative to `java.lang.String`. Java Strings are immutable and allocate on every manipulation, which makes them unsuitable for values that change on each message. An `XString` can be written in place, compared without allocating, and copied to and from messages without creating garbage.

Eliminating garbage is only half the problem. Objects held in application state survive long enough to be promoted across heap generations, and promotion is expensive. Avoiding it requires that the strings held in state be pooled and preallocated rather than created as needed. That is what a *poolable* string type provides.

## Declaring a Poolable String

Poolable string types are declared in the ADM model, not in application code. A String field or semantic type carrying `poolable="true"` causes the code generator to emit a dedicated subclass of `XString` for it, together with the factory used to pool and preallocate instances:

```xml
<types>
    <type name="ComplianceId" base="String" length="24" poolable="true"
          doc="Identifier attached to an order for compliance reporting."/>
</types>

<fields>
    <field name="complianceId" type="ComplianceId" id="1"/>
</fields>
```

A field may also be marked poolable directly, in which case the generated type is named after the field rather than the semantic type. The declaration syntax, the generated type, and the naming rules are covered in full under [Poolable String Types](/talon/developing-applications/modeling-messages-and-state/the-modeling-language.md#poolable-string-types).

## Working with Poolable Strings

Fields of a poolable string type are given accessors that copy the value in and out rather than handing out a reference:

| Method                        | Description                                                                                                                                                        |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `getXXXTo(factory)`           | Copies the field's value into an instance sourced from the given factory and returns it. Zero garbage when the factory is pool backed and has instances available. |
| `setXXXFrom(value)`           | Sets the field from an already encoded `XString`, avoiding a re-encode.                                                                                            |
| `getXXX()` / `setXXX(String)` | The plain String accessors, which allocate. Useful outside the hot path.                                                                                           |

There are two patterns in common use.

### Holding a value in application state

Source the string from a preallocated factory and copy the message value into it. This is the pattern to use whenever the value outlives the handler:

```java
private final ComplianceId.Factory complianceIdFactory =
    ComplianceId.newFactory("complianceId", 24, true, 1024, false, false);

@EventHandler
public void onNewOrder(NewOrder order, OrderState state) {
    // Copy the value out of the message into an instance from the pool.
    ComplianceId complianceId = order.getComplianceIdTo(complianceIdFactory);

    // Copy it into an outbound message.
    OrderAccepted accepted = OrderAccepted.create();
    accepted.setComplianceIdFrom(complianceId);

    // Retain it in application state.
    state.setComplianceId(complianceId);
}
```

Copying out of the message is not optional here. If the message itself is pooled, its field values are reset once the handler returns, so a reference retained in state would be left holding a value that no longer belongs to it.

### Using a working variable

Where the value does not outlive the handler, a single reusable instance is enough:

```java
private final ComplianceId complianceIdTemp = ComplianceId.create(true);

@EventHandler
public void onNewOrder(NewOrder order) {
    // Safe to overwrite on each invocation because handlers are single threaded
    // and the value is not retained beyond this call.
    order.getComplianceIdTo(complianceIdTemp);

    OrderAccepted accepted = OrderAccepted.create();
    accepted.setComplianceIdFrom(complianceIdTemp);
}
```

Note that this pattern retains the reference and so does not exercise the pooling capability of the type. It avoids allocation, not promotion.

## Preallocation

Preallocation is a property of the *factory*, not of the field. A factory created with a preallocation count fills its pool up front, so that instances taken during message processing are already resident and do not have to be allocated and later promoted:

```java
// name, stringLength, pooled, preallocationCount, threaded, isNative
ComplianceId.Factory factory =
    ComplianceId.newFactory("complianceId", 24, true, 1024, false, false);
```

* `stringLength` sizes the backing buffer of each instance. Size it for the longest value you expect. A value that exceeds it forces the backing storage to grow, which allocates.
* `pooled` determines whether the factory is backed by a pool at all. Preallocation is only meaningful when it is.
* `preallocationCount` is the number of instances created up front.
* `threaded` makes the backing pool thread safe. Leave it false for the single threaded handler path.
* `isNative` selects native backing buffers where enabled and supported.

Each generated type also exposes a default `FACTORY` for cases where a configured factory is not warranted.

Pools created this way are configurable at runtime alongside the platform's other pools. See [Tuning Pools](/talon/developing-applications/authoring-user-code/message-processing/processing-messages/handling-messages/coding-for-zero-garbage/tuning-pools.md).

## A Note on RawString

`XString` supersedes `RawString`, which remains present but is deprecated. New code should use `XString` and the generated poolable types; existing uses of `RawString` should migrate.

## See Also

* [Poolable String Types](/talon/developing-applications/modeling-messages-and-state/the-modeling-language.md#poolable-string-types) - declaring poolable strings and the code the generator emits
* [Coding for Zero Garbage](/talon/developing-applications/authoring-user-code/message-processing/processing-messages/handling-messages/coding-for-zero-garbage.md) - overview of zero garbage techniques
* [Tuning Pools](/talon/developing-applications/authoring-user-code/message-processing/processing-messages/handling-messages/coding-for-zero-garbage/tuning-pools.md) - configuring the pools that back preallocated types
* [Embedded Entities](/talon/developing-applications/authoring-user-code/message-processing/processing-messages/handling-messages/coding-for-zero-garbage/embedded-entities.md) - lifecycle-managed objects for complex messages
