Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
98732d7
feat: add JaCoCo configuration for code coverage and update POM struc…
peter-lawrey Oct 31, 2025
47d2866
feat: enhance POM configuration with JaCoCo options and update Maven …
peter-lawrey Oct 31, 2025
8e9d1d5
Apply standard licence headers across sources
peter-lawrey Oct 31, 2025
8613746
Tests: write HexDumpBytesTest mmap file to OS.getTarget()
peter-lawrey Oct 31, 2025
1af530d
Build: wire Surefire to JaCoCo argLine for sonar
peter-lawrey Oct 31, 2025
a3d716d
tests: add coverage for ByteStringReader/Writer, CanonicalPathUtil, a…
peter-lawrey Oct 31, 2025
67f8f53
tests: expand coverage
peter-lawrey Oct 31, 2025
86f11ed
Align Surefire argLine with JaCoCo and JPMS; add coverage tests
peter-lawrey Oct 31, 2025
63ef26d
Exercise UTF8 parsing and mapped bounds
peter-lawrey Oct 31, 2025
28da7ce
PR1: Hygiene and exception handling fixes
peter-lawrey Oct 31, 2025
de11292
PR2: Refactor inline assignments in BytesMarshaller (S1121)
peter-lawrey Oct 31, 2025
70265c2
PR3: Reduce cognitive complexity in RandomDataInput.readUtf8Limited (…
peter-lawrey Oct 31, 2025
e78fd7b
PR4: Enforce @NotNull contract in AbstractBytes constructor (S2637)
peter-lawrey Oct 31, 2025
7feb1d7
PR5: Suppress wildcard return warnings on factory methods (S1452)
peter-lawrey Oct 31, 2025
d0dc3c2
PR6: Guard reflective field access and document policy (S3011)
peter-lawrey Oct 31, 2025
610fb34
PR7: Replace broad Throwable catches with Exception + Error where saf…
peter-lawrey Oct 31, 2025
ba13a5d
Sonar: run Surefire with single fork to ensure JaCoCo writes exec
peter-lawrey Oct 31, 2025
f839cae
Sonar: remove debugForkedProcess to avoid noisy logs
peter-lawrey Oct 31, 2025
bf3a41a
Tests: add BytesInternal contentEqual and parseUtf8 boundary coverage…
peter-lawrey Oct 31, 2025
5d9b799
Tests: add HexDumpBytes wrap width=1 and RandomDataInput.readUtf8Limi…
peter-lawrey Oct 31, 2025
49ca57f
JaCoCo: baseline thresholds set to current levels (line=0.72, branch=…
peter-lawrey Oct 31, 2025
01123bc
Tests: align with adv/code-review improvements
peter-lawrey Oct 31, 2025
0e85999
Address outstanding ISSUES.md items
peter-lawrey Oct 31, 2025
7ad0c74
MethodWriter: rollback writePosition on any Throwable during encode (…
peter-lawrey Oct 31, 2025
277a760
Tests: consolidate and refactor
peter-lawrey Oct 31, 2025
9cfa4d8
Sonar/Jacoco: append exec and set explicit destFile for reliable cove…
peter-lawrey Oct 31, 2025
1173ac3
MethodWriter: add @SuppressWarnings("java:S1181") with rationale for …
peter-lawrey Oct 31, 2025
bfb3cbc
chore(license): auto-format license headers via license-maven-plugin
peter-lawrey Oct 31, 2025
9fce0d7
license: exclude AsciiDoc (*.adoc) and src/main/docs/** from header e…
peter-lawrey Oct 31, 2025
c336dd3
Tests: add write8bit round-trip, writeSkip behaviours, MappedBytes wr…
peter-lawrey Oct 31, 2025
f6f5089
test: fix writeSkip backtrack test to use length-prefixed writeUtf8 f…
peter-lawrey Oct 31, 2025
24097d4
build(pom): stop automatic SortPom runs; use sortpom:sort on request
peter-lawrey Oct 31, 2025
9d3cb43
refactor: rename files for consistency and update license header to A…
peter-lawrey Nov 1, 2025
2e2a2ed
replace the license header with a one-liner
peter-lawrey Nov 1, 2025
232bded
Merge remote-tracking branch 'origin/develop' into adv/add-jaccoco
peter-lawrey Nov 1, 2025
112b060
Merge remote-tracking branch 'origin/develop' into adv/add-jaccoco
peter-lawrey Nov 2, 2025
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
143 changes: 85 additions & 58 deletions pom.xml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/main/java/net/openhft/chronicle/bytes/AbstractBytes.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public abstract class AbstractBytes<U>

private final UncheckedRandomDataInput uncheckedRandomDataInput = new UncheckedRandomDataInputHolder();
@NotNull
protected BytesStore<?, U> bytesStore;
protected BytesStore<?, U> bytesStore = BytesStore.empty();
/** Offset, from {@link #start()}, of the next byte to read. */
protected long readPosition;
/** Highest byte index that may be written. */
Expand Down Expand Up @@ -116,7 +116,7 @@ public abstract class AbstractBytes<U>
@NonNegative long writeLimit,
String name)
throws ClosedIllegalStateException, ThreadingIllegalStateException {
super(bytesStore.isDirectMemory());
super(java.util.Objects.requireNonNull(bytesStore, "bytesStore").isDirectMemory());
this.bytesStore(bytesStore);
bytesStore.reserve(this);
readPosition = bytesStore.readPosition();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ protected Object doInvoke(Object proxy, Method method, Object[] args)
out.writeHexDumpDescription(method.getName());
out.writeStopBit(info.messageId());
info.encode(args, out);
} catch (Throwable t) {
} catch (Throwable t) { // restore previous behaviour: always roll back position on any failure
out.writePosition(pos);
throw t;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,10 @@ default void writeMarshallable(BytesOut<?> bytes)
String s = "# " + getClass().getName() + "\n" + bytes.toHexString();
bytes.releaseLast();
return s;
} catch (Throwable e) {
} catch (Exception e) {
return e.toString();
} catch (Error err) {
throw err;
} finally {
ValidatableUtil.endValidateDisabled();
}
Expand Down
44 changes: 37 additions & 7 deletions src/main/java/net/openhft/chronicle/bytes/BytesMarshaller.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ public class BytesMarshaller<T> {
public static final ClassLocal<BytesMarshaller> BYTES_MARSHALLER_CL
= ClassLocal.withInitial(BytesMarshaller::new);
private final FieldAccess[] fields;
/**
* Controls whether private fields are included via reflective access. When disabled, only
* publicly accessible fields are marshalled. This avoids reflective accessibility changes in
* restricted runtimes.
*/
static final boolean ALLOW_PRIVATE_FIELD_ACCESS = Jvm.getBoolean("bytes.marshaller.allowPrivateFields", true);

/**
* Constructs a BytesMarshaller for the specified class.
Expand Down Expand Up @@ -63,11 +69,30 @@ public static void getAllField(@NotNull Class<?> clazz, @NotNull Map<String, Fie
for (@NotNull Field field : clazz.getDeclaredFields()) {
if ((field.getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) != 0)
continue;
Jvm.setAccessible(field);
map.put(field.getName(), field);
if (ALLOW_PRIVATE_FIELD_ACCESS) {
// Intentionally limited and documented reflective access for marshalling private fields.
// This is centralised here to keep the surface small and auditable.
enableAccessible(field);
map.put(field.getName(), field);
} else {
// Only marshal fields that are already publicly accessible when private access is disabled.
final boolean publicField = Modifier.isPublic(field.getModifiers());
final boolean publicClass = Modifier.isPublic(field.getDeclaringClass().getModifiers());
if (publicField && publicClass) {
map.put(field.getName(), field);
}
}
}
}

/**
* Centralised, narrowly-scoped accessibility change with explicit suppression and justification.
*/
@SuppressWarnings("java:S3011")
private static void enableAccessible(Field field) {
Jvm.setAccessible(field);
}

/**
* Populates {@code t} by reading each field from {@code in} using reflection.
*/
Expand Down Expand Up @@ -331,8 +356,10 @@ protected void setValue(Object o, BytesIn<?> read)
if (c == null) {
c = (Object[]) Array.newInstance(field.getType().getComponentType(), elementCount);
field.set(o, c);
} else if (c.length != elementCount)
field.set(o, c = Arrays.copyOf(c, elementCount));
} else if (c.length != elementCount) {
c = Arrays.copyOf(c, elementCount);
field.set(o, c);
}
for (int i = 0; i < elementCount; i++) {
Object o2 = c[i];
if (o2 instanceof BytesMarshallable)
Expand Down Expand Up @@ -405,8 +432,10 @@ protected void setValue(Object o, BytesIn<?> read)
}
BytesUtil.checkArrayLength(length, read.readRemaining());

if (c == null)
field.set(o, c = collectionSupplier.get());
if (c == null) {
c = collectionSupplier.get();
field.set(o, c);
}
else
c.clear();

Expand Down Expand Up @@ -473,7 +502,8 @@ protected void setValue(Object o, BytesIn<?> read)
}
BytesUtil.checkArrayLength(numEntries, read.readRemaining());
if (m == null) {
field.set(o, m = collectionSupplier.get());
m = collectionSupplier.get();
field.set(o, m);
} else {
m.clear();
}
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/net/openhft/chronicle/bytes/HexDumpBytes.java
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,10 @@ public String toHexString() {
throwExceptionIfReleased(this);
if (lineLength() > 0) newLine();
return text.toString();
} catch (Throwable e) {
} catch (Exception e) {
return e.toString();
} catch (Error err) {
throw err;
}
}

Expand Down
58 changes: 36 additions & 22 deletions src/main/java/net/openhft/chronicle/bytes/RandomDataInput.java
Original file line number Diff line number Diff line change
Expand Up @@ -552,28 +552,9 @@ default <T extends Appendable & CharSequence> long readUtf8Limited(@NonNegative
long remaining = requireNonNegative(readLimit() - offset);
if (remaining < 1)
throw new BufferUnderflowException();

long utfLen;
if ((utfLen = readByte(offset++)) < 0) {
utfLen &= 0x7FL;
long b;
int count = 7;
while ((b = readByte(offset++)) < 0) {
utfLen |= (b & 0x7FL) << count;
count += 7;
}
if (b != 0) {
if (count > 56)
throw new IORuntimeException(
"Cannot read more than 9 stop bits of positive value");
utfLen |= (b << count);
} else {
if (count > 63)
throw new IORuntimeException(
"Cannot read more than 10 stop bits of negative value");
utfLen = ~utfLen;
}
}
StopBitDecoded decoded = decodeStopBit(this, offset);
long utfLen = decoded.value;
offset = decoded.nextOffset;
if (utfLen == -1)
return ~offset;
if (utfLen > maxUtf8Len)
Expand All @@ -585,6 +566,39 @@ default <T extends Appendable & CharSequence> long readUtf8Limited(@NonNegative
return offset + utfLen;
}

/** Minimal holder for a decoded stop-bit value and the next offset. */
final class StopBitDecoded {
public final long value;
public final long nextOffset;
StopBitDecoded(long value, long nextOffset) {
this.value = value;
this.nextOffset = nextOffset;
}
}

static StopBitDecoded decodeStopBit(@NotNull RandomDataInput in, long offset)
throws IORuntimeException, ClosedIllegalStateException {
long v = in.readByte(offset++);
if (v >= 0) return new StopBitDecoded(v, offset);
v &= 0x7FL;
long b;
int count = 7;
while ((b = in.readByte(offset++)) < 0) {
v |= (b & 0x7FL) << count;
count += 7;
}
if (b != 0) {
if (count > 56)
throw new IORuntimeException("Cannot read more than 9 stop bits of positive value");
v |= (b << count);
} else {
if (count > 63)
throw new IORuntimeException("Cannot read more than 10 stop bits of negative value");
v = ~v;
}
return new StopBitDecoded(v, offset);
}

/**
* Reads a char sequence from the given {@code offset}, encoded as Utf8. If length of Utf8
* encoding of the char sequence exceeds {@code maxUtf8Len}, {@code ClosedIllegalStateException}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ private ByteBuffers() {
try {
address = Jvm.getField(direct.getClass(), "address");
capacity = Jvm.getField(direct.getClass(), "capacity");
} catch (Throwable t) {
Jvm.warn().on(ByteBuffers.class, "Unable to access direct ByteBuffer fields", t);
} catch (Exception e) {
Jvm.warn().on(ByteBuffers.class, "Unable to access direct ByteBuffer fields", e);
}
ADDRESS = address;
CAPACITY = capacity;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,18 @@ private static Boolean java11ContentEqualUsingVectorizedMismatch(@NotNull final
}

final int length = (int) left.realReadRemaining();
final int invoke = (int) VECTORIZED_MISMATCH_METHOD_HANDLE.invoke(leftObject,
leftOffset,
rightObject,
rightOffset,
length,
0);
final int invoke;
try {
invoke = (int) VECTORIZED_MISMATCH_METHOD_HANDLE.invoke(leftObject,
leftOffset,
rightObject,
rightOffset,
length,
0);
} catch (Throwable t) { // MethodHandle.invoke declares Throwable
Jvm.warn().on(BytesInternal.class, t);
return null;
}

if (invoke >= 0)
return Boolean.FALSE;
Expand All @@ -244,9 +250,11 @@ private static Boolean java11ContentEqualUsingVectorizedMismatch(@NotNull final
}

return Boolean.TRUE;
} catch (Throwable e) {
} catch (Exception e) {
Jvm.warn().on(BytesInternal.class, e);
return null;
} catch (Error err) {
throw err;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ public class NativeBytesStore<U>
address = Jvm.getField(directBB, "address");
capacity = Jvm.getField(directBB, "capacity");
att = Jvm.getField(directBB, "att");
} catch (Throwable t) {
Jvm.warn().on(NativeBytesStore.class, "Unable to access ByteBuffer fields", t);
} catch (Exception e) {
Jvm.warn().on(NativeBytesStore.class, "Unable to access ByteBuffer fields", e);
}
BB_ADDRESS = address;
BB_CAPACITY = capacity;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,10 @@ public String toString() {
return "bytes is null";
try {
return "value: " + getValue();
} catch (Throwable e) {
} catch (Exception e) {
return "value: " + e;
} catch (Error err) {
throw err;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,8 +411,10 @@ public String toString() {
if (i < getCapacity())
sb.append(" ...");

} catch (Throwable e) {
} catch (Exception e) {
sb.append(" ").append(e);
} catch (Error err) {
throw err;
}
return sb.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,10 @@ public String toString() {
if (bytesStore == null) return "bytes is null";
try {
return "value: " + getValue();
} catch (Throwable e) {
} catch (Exception e) {
return e.toString();
} catch (Error err) {
throw err;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,10 @@ public String toString() {
return "addressForRead is 0";
try {
return "value: " + getValue();
} catch (Throwable e) {
} catch (Exception e) {
return "value: " + e;
} catch (Error err) {
throw err;
}
}

Expand Down
Loading