Tema: java
-
Escribir una prueba unitaria en JUnit 5 y xUnit.net: anotaciones, ciclo de vida y casos parametrizados en paralelo
JUnit Jupiter marca las pruebas con @Test, ejecuta @BeforeEach y @AfterEach alrededor de cada una sobre una instancia nueva de forma predeterminada, y conduce los casos basados en datos con @ParameterizedTest más una anotación de fuente; xUnit.net usa [Fact], el constructor e IDisposable para la configuración por prueba sobre una instancia nueva, [Theory] con [InlineData] para los casos, y fixtures para el contexto costoso compartido. Escribir pruebas con la misma forma en ambos mantiene alineadas las convenciones de un equipo políglota.
-
Dimensionar una JVM dentro de un contenedor: porcentaje de heap, memoria fuera del heap y número de CPU
La JVM lee por defecto los límites de cgroup (UseContainerSupport) y dimensiona el heap como un porcentaje de la memoria del contenedor, no del host; el heap es solo parte de la huella, así que conviene fijar MaxRAMPercentage dejando espacio para el metaspace, las pilas de hilos, los búferes directos y la caché de código, comprobar el número de CPU que ve la JVM, y verificar con -Xlog:os+container y el seguimiento de memoria nativa antes de confiar en un límite.
-
Maven frente a Gradle: qué necesita quien se inicia para compilar el proyecto JVM de otra persona
Maven describe un proyecto de forma declarativa en pom.xml y ejecuta fases de ciclo de vida fijas (validate, compile, test, package, verify, install, deploy) con objetivos de plugin vinculados a ellas; Gradle ejecuta un grafo de tareas configurado mediante scripts build.gradle(.kts) y plugins. Ambos resuelven dependencias transitivas, pero con reglas de conflicto distintas (Maven: la definición más cercana; Gradle: la versión más alta), y ambos incluyen un script wrapper que fija la versión de la herramienta de compilación.
-
Records de Java, tipos sellados y pattern matching para switch
Los records (JDK 16) son portadores de datos transparentes e inmutables con un constructor canónico generado, accesores, equals, hashCode y toString; los tipos sellados (JDK 17) restringen qué clases pueden extenderlos o implementarlos, de modo que un switch con patrones (JDK 21) sobre la jerarquía pueda comprobarse por exhaustividad. Juntos le dan a Java un tipo suma ligero.
-
Recolección de basura en la JVM: los recolectores, los valores por defecto y las pocas flags que vale la pena configurar
HotSpot incluye Serial, Parallel, G1 y ZGC; elige G1 en máquinas que considera de clase servidor (dos o más procesadores y al menos 1792 MB) y Serial en las demás, con un heap máximo por defecto de un cuarto de la memoria. Para la mayoría de los servicios, las flags que vale la pena configurar son el heap máximo, el registro de GC y, solo después de leer los registros, un recolector o un objetivo de tiempo de pausa.
-
Deserialización de datos no confiables: pickle y la serialización de Java
Los formatos nativos de serialización de objetos indican al receptor que construya objetos arbitrarios, y construir objetos ejecuta código; la documentación de pickle de Python afirma sin rodeos que el módulo no es seguro. No deserializar nunca estos formatos a partir de una entrada no confiable; donde una interfaz heredada lo obligue, restringir las clases que el flujo puede nombrar y firmar la carga útil.
-
Tras migrar un servicio de la JVM a hilos virtuales, ¿qué cambió en el rendimiento, la memoria y los incidentes de anclaje, y qué hubo que reescribir?
Pregunta abierta: la JEP 444 afirma que el anclaje (pinning) no hace incorrecta una aplicación, pero puede dificultar su escalabilidad, y la JEP 491, entregada en JDK 24, elimina el anclaje para los bloques synchronized; en los servicios que pasaron el manejo de solicitudes a hilos virtuales, ¿qué efecto tuvo el cambio sobre el rendimiento y la memoria, qué incidentes de anclaje o agotamiento de pools se produjeron, y qué código y bibliotecas hubo que modificar?
-
Los hilos virtuales de Java en resumen: qué cambia y qué no
La JEP 444 (JDK 21) añade los hilos virtuales: hilos económicos que el JDK planifica sobre un pequeño pool de hilos de plataforma portadores, de los que se desmontan mientras están bloqueados en la mayoría de las operaciones de E/S del JDK, de modo que el código de un hilo por solicitud escala sin un estilo asíncrono. No son más rápidos, no deben agruparse nunca en un pool, y hasta la JEP 491 (JDK 24) el bloqueo dentro de un synchronized anclaba al portador.
-
Tokens de formato de fecha y hora: equivalencias entre strftime, Java, Go, .NET y Moment/date-fns
La misma letra significa cosas distintas según la biblioteca de formato: la Y mayúscula de Java es el año de semana y no el año natural, y la D es el día del año en Java y date-fns, pero el día del mes en Moment. Esta tabla de tokens sirve para revisar una cadena de formato generada antes de fiarse de ella.
-
Streams de Java frente a bucles: cuándo un pipeline es más claro y cuándo no
Un stream es un pipeline perezoso de operaciones intermedias cerrado por una única operación terminal; se lee bien para filter, map y collect sobre una colección, pero la documentación del paquete desaconseja los efectos secundarios en las lambdas, un stream no se puede reutilizar, las excepciones comprobadas no encajan y un bucle es más claro para la salida anticipada con estado, el trabajo basado en índices y la mutación.
-
Por qué las aplicaciones ignoran el almacén de confianza del SO: cacerts de Java, certifi de Python, Node.js y curl
Añadir una CA al almacén de confianza del sistema operativo no hace que todas las aplicaciones confíen en ella. Java, muchas instalaciones de Python, Node.js y ciertas compilaciones de curl pueden tener su propio paquete de CA o keystore, cada uno con su ubicación y su variable de entorno para sobrescribirlo, de modo que un error de certificado puede persistir tras la corrección a nivel de SO.
Legible por máquina: JSON