Tema: java
-
Writing a unit test in JUnit 5 and xUnit.net: annotations, lifecycle and parameterised cases side by side
JUnit Jupiter marks tests with @Test, runs @BeforeEach and @AfterEach around each one on a fresh instance by default, and drives data-driven cases with @ParameterizedTest plus a source annotation; xUnit.net uses [Fact], the constructor and IDisposable for per-test setup on a fresh instance, [Theory] with [InlineData] for cases, and fixtures for shared expensive context. Writing tests with the same shape in both keeps a polyglot team's conventions aligned.
-
Sizing a JVM inside a container: heap percentage, non-heap memory and CPU count
The JVM reads cgroup limits by default (UseContainerSupport) and sizes the heap as a percentage of the container's memory, not the host's; heap is only part of the footprint, so set MaxRAMPercentage to leave room for metaspace, thread stacks, direct buffers and code cache, check the CPU count the JVM sees, and verify with -Xlog:os+container and native memory tracking before trusting a limit.
-
Maven versus Gradle: what a newcomer needs to build someone else's JVM project
Maven describes a project declaratively in pom.xml and runs fixed lifecycle phases (validate, compile, test, package, verify, install, deploy) with plugin goals bound to them; Gradle runs a graph of tasks configured by build.gradle(.kts) scripts and plugins. Both resolve transitive dependencies but with different conflict rules (Maven: nearest definition; Gradle: highest version), and both ship a wrapper script that pins the build tool version.
-
Java records, sealed types and pattern matching for switch
Records (JDK 16) are transparent, immutable data carriers with a generated canonical constructor, accessors, equals, hashCode and toString; sealed types (JDK 17) restrict which classes may extend or implement them so that a pattern switch (JDK 21) over the hierarchy can be checked for exhaustiveness. Together they give Java a lightweight sum type.
-
JVM garbage collection: the collectors, the defaults and the few flags worth setting
HotSpot ships Serial, Parallel, G1 and ZGC; it picks G1 on machines it considers server-class (two or more processors and at least 1792 MB) and Serial otherwise, with a default maximum heap of a quarter of memory. For most services the flags worth setting are the maximum heap, GC logging, and only after reading logs a collector or a pause-time goal.
-
Deserialisation of untrusted data: pickle and Java serialization
Native object serialisation formats instruct the receiver to construct arbitrary objects, and constructing objects runs code; Python's pickle documentation says outright that the module is not secure. Never deserialise these formats from untrusted input; where a legacy interface forces it, restrict the classes the stream may name and sign the payload.
-
After moving a JVM service to virtual threads, what changed in throughput, memory and pinning incidents, and what had to be rewritten?
Open question: JEP 444 states that pinning does not make an application incorrect but might hinder its scalability, and JEP 491, delivered in JDK 24, removes pinning for synchronized blocks; for services that switched request handling to virtual threads, what did the change do to throughput and memory, which pinning or pool-exhaustion incidents occurred, and which code and libraries had to change?
-
Java virtual threads in outline: what changes and what does not
JEP 444 (JDK 21) adds virtual threads: cheap threads scheduled by the JDK onto a small pool of carrier platform threads, which unmount while blocked on most JDK I/O so that thread-per-request code scales without an asynchronous style. They are not faster, must never be pooled, and until JEP 491 (JDK 24) blocking inside synchronized pinned the carrier.
-
Java streams versus loops: when a pipeline is clearer and when it is not
A stream is a lazy pipeline of intermediate operations closed by one terminal operation; it reads well for filter, map and collect over a collection, but the package documentation discourages side effects in the lambdas, a stream cannot be reused, checked exceptions do not fit, and a loop is clearer for early exit with state, index-based work and mutation.
Legível por máquina: JSON