protected static Value makeValue(Object value) {
		return switch (value) {
			case Void v -> Value.newBuilder().setNullValue(Null.getDefaultInstance()).build();
			case Boolean b -> Value.newBuilder().setBoolValue(b).build();
			case Byte b -> Value.newBuilder().setByteValue(b).build();
			case Character c -> Value.newBuilder().setCharValue(c).build();
			case Short s -> Value.newBuilder().setShortValue(s).build();
			case Integer i -> Value.newBuilder().setIntValue(i).build();
			case Long l -> Value.newBuilder().setLongValue(l).build();
			case String s -> Value.newBuilder().setStringValue(s).build();
			case boolean[] ba -> Value.newBuilder()
					.setBoolArrValue(
						BoolArr.newBuilder().addAllArr(Arrays.asList(ArrayUtils.toObject(ba))))
					.build();
			case byte[] ba -> Value.newBuilder().setBytesValue(ByteString.copyFrom(ba)).build();
			case char[] ca -> Value.newBuilder().setCharArrValue(new String(ca)).build();
			case short[] sa -> Value.newBuilder()
					.setShortArrValue(ShortArr.newBuilder()
							.addAllArr(
								Stream.of(ArrayUtils.toObject(sa)).map(s -> (int) s).toList()))
					.build();
			case int[] ia -> Value.newBuilder()
					.setIntArrValue(
						IntArr.newBuilder().addAllArr(IntStream.of(ia).mapToObj(i -> i).toList()))
					.build();
			case long[] la -> Value.newBuilder()
					.setLongArrValue(
						LongArr.newBuilder().addAllArr(LongStream.of(la).mapToObj(l -> l).toList()))
					.build();
			case String[] sa -> Value.newBuilder()
					.setStringArrValue(StringArr.newBuilder().addAllArr(List.of(sa)))
					.build();
			case Address a -> Value.newBuilder().setAddressValue(makeAddr(a)).build();
			case AddressRange r -> Value.newBuilder().setRangeValue(makeAddrRange(r)).build();
			case TraceObject o -> Value.newBuilder().setChildDesc(makeObjDesc(o)).build();
			default -> throw new AssertionError(
				"Cannot encode value: " + value + "(type=" + value.getClass() + ")");
		};
	}
The likely cause of this failing is that the remote end has closed the socket.
However, we don't return, because there may be commands still in the queue, and
we should process them until we reach the end of input. This will ensure clients
that brazenly send a bunch of commands and then disconnect before receiving the
replies will have their commands processed, even if unsuccessfully.
Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiHandler.java