Nota : ¡Estoy trabajando en la versión 2 de esta guía y necesito tu ayuda! Utilice este formulario para enviarme comentarios sobre lo que cree que debería incluirse en la próxima versión. ¡Gracias!
Java es uno de los lenguajes de programación más populares que existen, pero a nadie parece gustarle usarlo. Bueno, Java es en realidad un buen lenguaje de programación y, dado que Java 8 salió recientemente, decidí compilar una lista de bibliotecas, prácticas y herramientas para mejorar el uso de Java. "Mejor" es subjetivo, por lo que recomendaría tomar las partes que le hablan y usarlas, en lugar de intentar usarlas todas a la vez. No dudes en enviar solicitudes de extracción sugiriendo adiciones.
Este artículo fue publicado originalmente en mi blog.
Lea esto en otros idiomas: inglés, 简体中文
Tradicionalmente, Java se programaba en un estilo empresarial JavaBean muy detallado. El nuevo estilo es mucho más limpio, más correcto y más agradable a la vista.
Una de las cosas más simples que hacemos como programadores es transmitir datos. La forma tradicional de hacer esto es definir un JavaBean:
public class DataHolder {
private String data ;
public DataHolder () {
}
public void setData ( String data ) {
this . data = data ;
}
public String getData () {
return this . data ;
}
}
Esto es detallado y un desperdicio. Incluso si su IDE generó automáticamente este código, es un desperdicio. Así que no hagas esto.
En cambio, prefiero el estilo de estructura C para escribir clases que simplemente contienen datos:
public class DataHolder {
public final String data ;
public DataHolder ( String data ) {
this . data = data ;
}
}
Esta es una reducción en el número de líneas de código a la mitad. Además, esta clase es inmutable a menos que la extienda, por lo que podemos razonar más fácilmente ya que sabemos que no se puede cambiar.
Si está almacenando objetos como Map o List que se pueden modificar fácilmente, debe usar ImmutableMap o ImmutableList, que se analiza en la sección sobre inmutabilidad.
Si tiene un objeto bastante complicado para el que desea crear una estructura, considere el patrón Builder.
Creas una clase interna estática que construirá tu objeto. Utiliza un estado mutable, pero tan pronto como llame a build, emitirá un objeto inmutable.
Imaginemos que tuviéramos un DataHolder más complicado. El constructor podría verse así:
public class ComplicatedDataHolder {
public final String data ;
public final int num ;
// lots more fields and a constructor
public static class Builder {
private String data ;
private int num ;
public Builder data ( String data ) {
this . data = data ;
return this ;
}
public Builder num ( int num ) {
this . num = num ;
return this ;
}
public ComplicatedDataHolder build () {
return new ComplicatedDataHolder ( data , num ); // etc
}
}
}
Entonces para usarlo:
final ComplicatedDataHolder cdh = new ComplicatedDataHolder . Builder ()
. data ( "set this" )
. num ( 523 )
. build ();
Hay mejores ejemplos de constructores en otros lugares, pero esto debería darle una idea de cómo es. Esto termina con gran parte del texto estándar que estábamos tratando de evitar, pero te brinda objetos inmutables y una interfaz muy fluida.
En lugar de crear objetos constructores a mano, considere usar una de las muchas bibliotecas que pueden ayudarlo a generar constructores.
Si crea muchos objetos inmutables a mano, considere usar el procesador de anotaciones para generarlos automáticamente desde las interfaces. Esto minimiza el código repetitivo, reduce la probabilidad de errores y promueve la inmutabilidad. Consulte esta presentación para obtener una discusión interesante sobre algunos de los problemas con los patrones de codificación normales de Java.
Algunas bibliotecas excelentes para la generación de código son las inmutables, el valor automático de Google y Lombok.
Las excepciones marcadas deben usarse con precaución, en todo caso. Obligan a sus usuarios a agregar muchos bloques try/catch y a incluir sus excepciones en los suyos. Mejor es hacer que sus excepciones extiendan RuntimeException. Esto permite a sus usuarios manejar sus excepciones de la manera que quieran, en lugar de obligarlos a manejar/declarar que se produce cada vez, lo que contamina el código.
Un truco ingenioso es poner RuntimeExceptions en la declaración de lanzamientos de su método. Esto no tiene ningún efecto en el compilador, pero informará a sus usuarios a través de la documentación que se pueden generar estas excepciones.
Esta es más una sección de ingeniería de software que una sección de Java, pero una de las mejores formas de escribir software comprobable es utilizar la inyección de dependencia (DI). Debido a que Java fomenta fuertemente el diseño OO, para crear software comprobable, es necesario utilizar DI.
En Java, esto normalmente se hace con Spring Framework. Tiene un cableado basado en código o un cableado basado en configuración XML. Si utiliza la configuración XML, es importante que no abuse de Spring debido a su formato de configuración basado en XML. No debería haber absolutamente ninguna lógica o estructuras de control en XML. Sólo debería inyectar dependencias.
Buenas alternativas al uso de Spring son la biblioteca Dagger de Google y Square o Guice de Google. No utilizan el formato de archivo de configuración XML de Spring y, en su lugar, colocan la lógica de inyección en anotaciones y en código.
Intente evitar el uso de valores nulos cuando pueda. No devuelva colecciones nulas cuando debería haber devuelto una colección vacía. Si va a utilizar nulo, considere la anotación @Nullable. IntelliJ IDEA tiene soporte integrado para la anotación @Nullable.
Lea más sobre por qué no utilizar valores nulos en El peor error de la informática.
Si está utilizando Java 8, puede utilizar el nuevo y excelente tipo Opcional. Si un valor puede estar presente o no, envuélvalo en una clase opcional como esta:
public class FooWidget {
private final String data ;
private final Optional < Bar > bar ;
public FooWidget ( String data ) {
this ( data , Optional . empty ());
}
public FooWidget ( String data , Optional < Bar > bar ) {
this . data = data ;
this . bar = bar ;
}
public Optional < Bar > getBar () {
return bar ;
}
}
Ahora está claro que los datos nunca serán nulos, pero la barra puede estar presente o no. Opcional tiene métodos como isPresent , lo que puede hacer que parezca que no hay mucha diferencia con simplemente marcar null . Pero te permite escribir declaraciones como:
final Optional < FooWidget > fooWidget = maybeGetFooWidget ();
final Baz baz = fooWidget . flatMap ( FooWidget :: getBar )
. flatMap ( BarWidget :: getBaz )
. orElse ( defaultBaz );
Lo cual es mucho mejor que los controles encadenados si son nulos. El único inconveniente de usar Opcional es que la biblioteca estándar no tiene un buen soporte Opcional, por lo que aún es necesario tratar con valores nulos allí.
A menos que tenga una buena razón para hacerlo de otra manera, las variables, clases y colecciones deben ser inmutables.
Las variables se pueden hacer inmutables con final :
final FooWidget fooWidget ;
if ( condition ()) {
fooWidget = getWidget ();
} else {
try {
fooWidget = cachedFooWidget . get ();
} catch ( CachingException e ) {
log . error ( "Couldn't get cached value" , e );
throw e ;
}
}
// fooWidget is guaranteed to be set here
Ahora puedes estar seguro de que fooWidget no será reasignado accidentalmente. La palabra clave final funciona con bloques if/else y con bloques try/catch. Por supuesto, si el fooWidget en sí no es inmutable, podrías mutarlo fácilmente.
Las colecciones deben, siempre que sea posible, utilizar las clases Guava ImmutableMap, ImmutableList o ImmutableSet. Estos tienen constructores para que puedas construirlos dinámicamente y luego marcarlos como inmutables llamando al método de compilación.
Las clases deben volverse inmutables declarando campos inmutables (a través de final ) y usando colecciones inmutables. Opcionalmente, puede hacer que la clase sea final para que no pueda extenderse ni hacerse mutable.
Tenga cuidado si agrega muchos métodos a una clase Util.
public class MiscUtil {
public static String frobnicateString ( String base , int times ) {
// ... etc
}
public static void throwIfCondition ( boolean condition , String msg ) {
// ... etc
}
}
Estas clases, al principio, parecen atractivas porque los métodos que las contienen no pertenecen a ningún lugar en particular. Así que los incluyes todos aquí en nombre de la reutilización del código.
El remedio es peor que la enfermedad. Coloque estas clases donde pertenecen y refactorice agresivamente. No nombre clases, paquetes o bibliotecas de forma demasiado genérica, como "MiscUtils" o "ExtrasLibrary". Esto fomenta el volcado de código no relacionado allí.
El formateo es mucho menos importante de lo que la mayoría de los programadores creen. ¿La coherencia demuestra que te preocupas por tu oficio y ayuda a otros a leer? Absolutamente. Pero no perdamos un día agregando espacios a los bloques if para que "coincidan".
Si es absolutamente necesario una guía de formato de código, le recomiendo la guía de estilo Java de Google. La mejor parte de esa guía es la sección Prácticas de programación. Definitivamente vale la pena leerlo.
Es importante documentar el código de cara al usuario. Y esto significa usar ejemplos y descripciones sensatas de variables, métodos y clases.
El corolario de esto es no documentar lo que no necesita ser documentado. Si no tiene nada que decir sobre qué es un argumento, o si es obvio, no lo documente. La documentación repetitiva es peor que ninguna documentación, ya que engaña a los usuarios haciéndoles creer que hay documentación.
Java 8 tiene una buena secuencia y sintaxis lambda. Podrías escribir código como este:
final List < String > filtered = list . stream ()
. filter ( s -> s . startsWith ( "s" ))
. map ( s -> s . toUpperCase ())
. collect ( Collectors . toList ());
En lugar de esto:
final List < String > filtered = new ArrayList <>();
for ( String str : list ) {
if ( str . startsWith ( "s" ) {
filtered . add ( str . toUpperCase ());
}
}
Esto le permite escribir código más fluido y más legible.
Implementar Java correctamente puede resultar un poco complicado. Hay dos formas principales de implementar Java hoy en día: usar un marco o usar una solución propia que sea más flexible.
Debido a que implementar Java no es fácil, se han creado marcos que pueden ayudar. Dos de los mejores son Dropwizard y Spring Boot. El marco Play también puede considerarse uno de estos marcos de implementación.
Todos ellos intentan reducir la barrera para que su código salga por la puerta. Son especialmente útiles si eres nuevo en Java o si necesitas hacer las cosas rápidamente. Las implementaciones de un solo JAR son más fáciles que las complicadas implementaciones de WAR o EAR.
Sin embargo, pueden ser algo inflexibles y bastante testarudos, por lo que si su proyecto no se ajusta a las decisiones que tomaron los desarrolladores de su marco, tendrá que migrar a una configuración más personalizada.
Buena alternativa : Gradle.
Maven sigue siendo la herramienta estándar para crear, empaquetar y ejecutar sus pruebas. Hay alternativas, como Gradle, pero no tienen la misma adopción que Maven. Si eres nuevo en Maven, deberías comenzar con Maven con el ejemplo.
Me gusta tener un POM raíz con todas las dependencias externas que quieras usar. Se verá así. Este POM raíz tiene sólo una dependencia externa, pero si su producto es lo suficientemente grande, tendrá docenas. Su POM raíz debe ser un proyecto en sí mismo: en control de versiones y lanzado como cualquier otro proyecto Java.
Si cree que etiquetar su POM raíz para cada cambio de dependencia externa es demasiado, no ha perdido una semana rastreando errores de dependencia entre proyectos.
Todos sus proyectos Maven incluirán su POM raíz y toda la información de su versión. De esta manera, obtendrá la versión seleccionada por su empresa de cada dependencia externa y todos los complementos de Maven correctos. Si necesita incorporar dependencias externas, funciona así:
< dependencies >
< dependency >
< groupId >org.third.party</ groupId >
< artifactId >some-artifact</ artifactId >
</ dependency >
</ dependencies >
Si desea dependencias internas, eso debe ser administrado por el administrador de cada proyecto individual. sección. De lo contrario, sería difícil mantener el número de versión raíz de POM en orden.
Una de las mejores partes de Java es la enorme cantidad de bibliotecas de terceros que hacen de todo. Básicamente, cada API o kit de herramientas tiene un SDK de Java y es fácil incorporarlo con Maven.
Y esas bibliotecas Java dependen de versiones específicas de otras bibliotecas. Si ingresa suficientes bibliotecas, obtendrá conflictos de versiones, es decir, algo como esto:
Foo library depends on Bar library v1.0
Widget library depends on Bar library v0.9
¿Qué versión se incorporará a su proyecto?
Con el complemento de convergencia de dependencias de Maven, la compilación generará un error si sus dependencias no usan la misma versión. Entonces, tienes dos opciones para resolver el conflicto:
La elección de cuál elegir depende de su situación: si desea realizar un seguimiento de la versión de un proyecto, entonces tiene sentido excluirlo. Por otro lado, si quieres ser explícito al respecto, puedes elegir una versión, aunque necesitarás actualizarla cuando actualices las otras dependencias.
Obviamente, necesita algún tipo de servidor de integración continua que cree continuamente sus versiones SNAPSHOT y compilaciones de etiquetas basadas en etiquetas git.
Jenkins y Travis-CI son opciones naturales.
La cobertura de código es útil y Cobertura tiene un buen complemento Maven y soporte CI. Existen otras herramientas de cobertura de código para Java, pero yo he usado Cobertura.
Necesita un lugar para colocar los JAR, WAR y EAR que cree, por lo que necesitará un repositorio.
Las opciones comunes son Artifactory y Nexus. Ambos funcionan y tienen sus pros y sus contras.
Deberías tener tu propia instalación de Artifactory/Nexus y reflejar tus dependencias en ella. Esto evitará que su compilación se rompa debido a que algún repositorio de Maven ascendente dejó de funcionar.
Así que ahora tienes tu código compilado, tu repositorio configurado y necesitas sacar tu código a tu entorno de desarrollo y eventualmente llevarlo a producción. No escatime aquí, porque automatizar esto dará sus frutos durante mucho tiempo.
Chef, Puppet y Ansible son opciones típicas. He escrito una alternativa llamada Squadron, que, por supuesto, creo que deberías consultar porque es más fácil acertar que las alternativas.
Independientemente de la herramienta que elija, no olvide automatizar sus implementaciones.
Probablemente la mejor característica de Java es la gran cantidad de bibliotecas que tiene. Esta es una pequeña colección de bibliotecas que probablemente sean aplicables al grupo más grande de personas.
La biblioteca estándar de Java, que alguna vez fue un sorprendente paso adelante, ahora parece que le faltan varias características clave.
El proyecto Apache Commons tiene un montón de bibliotecas útiles.
Commons Codec tiene muchos métodos útiles de codificación/decodificación para Base64 y cadenas hexadecimales. No pierdas el tiempo reescribiéndolos.
Commons Lang es la biblioteca de referencia para la manipulación y creación de cadenas, conjuntos de caracteres y un montón de métodos de utilidad diversos.
Commons IO tiene todos los métodos relacionados con archivos que pueda desear. Tiene FileUtils.copyDirectory, FileUtils.writeStringToFile, IOUtils.readLines y mucho más.
Guava es la excelente biblioteca de Google "esto es lo que falta en Java". Es casi difícil resumir todo lo que me gusta de esta biblioteca, pero lo intentaré.
El caché es una forma sencilla de obtener un caché en memoria que se puede utilizar para almacenar en caché el acceso a la red, el acceso al disco, memorizar funciones o cualquier cosa. Simplemente implemente un CacheBuilder que le indique a Guava cómo construir su caché y ¡listo!
Colecciones inmutables . Hay muchos de estos: ImmutableMap, ImmutableList o incluso ImmutableSortedMultiSet si ese es tu estilo.
También me gusta escribir colecciones mutables al estilo Guava:
// Instead of
final Map < String , Widget > map = new HashMap <>();
// You can use
final Map < String , Widget > map = Maps . newHashMap ();
Hay clases estáticas para Listas, Mapas, Conjuntos y más. Son más limpios y fáciles de leer.
Si está atascado con Java 6 o 7, puede usar la clase Collections2, que tiene métodos como filtrar y transformar. Le permiten escribir código fluido sin el soporte de secuencias de Java 8.
Guava también tiene cosas simples, como un Joiner que une cadenas en separadores y una clase para manejar interrupciones ignorándolas.
La biblioteca Gson de Google es una biblioteca de análisis JSON simple y rápida. Funciona así:
final Gson gson = new Gson ();
final String json = gson . toJson ( fooWidget );
final FooWidget newFooWidget = gson . fromJson ( json , FooWidget . class );
Es realmente fácil y es un placer trabajar con él. La guía de usuario de Gson tiene muchos más ejemplos.
Una de mis constantes molestias con Java es que no tiene tuplas integradas en la biblioteca estándar. Afortunadamente, el proyecto de tuplas de Java soluciona ese problema.
Es fácil de usar y funciona muy bien:
Pair < String , Integer > func ( String input ) {
// something...
return Pair . with ( stringResult , intResult );
}
Javaslang es una biblioteca funcional, diseñada para agregar características faltantes que deberían haber sido parte de Java 8. Algunas de estas características son
Existen varias bibliotecas de Java que dependen de las colecciones de Java originales. Estos están restringidos para seguir siendo compatibles con clases que fueron creadas con un enfoque orientado a objetos y diseñadas para ser mutables. Las colecciones Javaslang para Java son una versión completamente nueva, inspirada en Haskell, Clojure y Scala. Están creados con un enfoque funcional y siguen un diseño inmutable.
Código como este es automáticamente seguro para subprocesos y no requiere try-catch:
// Success/Failure containing the result/exception
public static Try < User > getUser ( int userId ) {
return Try . of (() -> DB . findUser ( userId ))
. recover ( x -> Match . of ( x )
. whenType ( RemoteException . class ). then ( e -> ...)
. whenType ( SQLException . class ). then ( e -> ...));
}
// Thread-safe, reusable collections
public static List < String > sayByeBye () {
return List . of ( "bye, " bye ", "collect" , "mania" )
. map ( String :: toUpperCase )
. intersperse ( " " );
}
Joda-Time es fácilmente la mejor biblioteca de tiempos que he usado. Sencillo, directo y fácil de probar. ¿Qué más se puede pedir?
Sólo necesitas esto si aún no estás en Java 8, ya que tiene su propia biblioteca de tiempo nueva que no apesta.
Lombok es una biblioteca interesante. A través de anotaciones, le permite reducir el texto estándar que tanto sufre Java.
¿Quieres definidores y captadores para las variables de tu clase? Simple:
public class Foo {
@ Getter @ Setter private int var ;
}
Ahora puedes hacer esto:
final Foo foo = new Foo ();
foo . setVar ( 5 );
Y hay mucho más. Aún no he usado Lombok en producción, pero no puedo esperar para hacerlo.
Buenas alternativas : Jersey o Spark
Hay dos campos principales para realizar servicios web RESTful en Java: JAX-RS y todo lo demás.
JAX-RS es la forma tradicional. Combina anotaciones con interfaces e implementaciones para formar el servicio web usando algo como Jersey. Lo bueno de esto es que puedes crear clientes fácilmente solo con la clase de interfaz.
El marco Play es una versión radicalmente diferente de los servicios web en la JVM: tienes un archivo de rutas y luego escribes las clases a las que se hace referencia en esas rutas. En realidad, es un marco MVC completo, pero puede usarlo fácilmente solo para servicios web REST.
Está disponible tanto para Java como para Scala. Sufre un poco por ser el primero en Scala, pero aún así es bueno usarlo en Java.
Si está acostumbrado a micromarcos como Flask en Python, Spark le resultará muy familiar. Funciona especialmente bien con Java 8.
Existen muchas soluciones de registro de Java. Mi favorito es SLF4J porque es extremadamente conectable y puede combinar registros de muchos marcos de registro diferentes al mismo tiempo. ¿Tiene un proyecto extraño que utiliza java.util.logging, JCL y log4j? SLF4J es para ti.
El manual de dos páginas es prácticamente todo lo que necesita para comenzar.
No me gustan los marcos ORM pesados porque me gusta SQL. Así que escribí muchas plantillas JDBC y fue algo difícil de mantener. jOOQ es una solución mucho mejor.
Le permite escribir SQL en Java de forma segura:
// Typesafely execute the SQL statement directly with jOOQ
Result < Record3 < String , String , String >> result =
create . select ( BOOK . TITLE , AUTHOR . FIRST_NAME , AUTHOR . LAST_NAME )
. from ( BOOK )
. join ( AUTHOR )
. on ( BOOK . AUTHOR_ID . equal ( AUTHOR . ID ))
. where ( BOOK . PUBLISHED_IN . equal ( 1948 ))
. fetch ();
Usando esto y el patrón DAO, puedes hacer que el acceso a la base de datos sea muy sencillo.
Las pruebas son fundamentales para su software. Estos paquetes ayudan a hacerlo más fácil.
Buena alternativa : TestNG.
jUnit no necesita presentación. Es la herramienta estándar para pruebas unitarias en Java.
Pero probablemente no estés utilizando jUnit en todo su potencial. jUnit admite pruebas parametrizadas, reglas para evitar que usted escriba tanto texto repetitivo, teorías para probar ciertos códigos de forma aleatoria y suposiciones.
Si ha realizado su inyección de dependencia, aquí es donde vale la pena: burlarse del código que tiene efectos secundarios (como hablar con un servidor REST) y aún afirmar el comportamiento del código que lo llama.
jMock es la herramienta de burla estándar para Java. Se parece a esto:
public class FooWidgetTest {
private Mockery context = new Mockery ();
@ Test
public void basicTest () {
final FooWidgetDependency dep = context . mock ( FooWidgetDependency . class );
context . checking ( new Expectations () {{
oneOf ( dep ). call ( with ( any ( String . class )));
atLeast ( 0 ). of ( dep ). optionalCall ();
}});
final FooWidget foo = new FooWidget ( dep );
Assert . assertTrue ( foo . doThing ());
context . assertIsSatisfied ();
}
}
Esto configura una FooWidgetDependency a través de jMock y luego agrega expectativas. Esperamos que el método de llamada de dep se llame una vez con alguna cadena y que el método de llamada opcional de dep se llame cero o más veces.
Si tiene que configurar la misma dependencia una y otra vez, probablemente debería ponerla en un dispositivo de prueba y afirmarIsSatisfied en un dispositivo @After .
¿Alguna vez haces esto con jUnit?
final List < String > result = some . testMethod ();
assertEquals ( 4 , result . size ());
assertTrue ( result . contains ( "some result" ));
assertTrue ( result . contains ( "some other result" ));
assertFalse ( result . contains ( "shouldn't be here" ));
Esto es simplemente una repetición molesta. AssertJ resuelve esto. Puedes transformar el mismo código en esto:
assertThat ( some . testMethod ()). hasSize ( 4 )
. contains ( "some result" , "some other result" )
. doesNotContain ( "shouldn't be here" );
Esta interfaz fluida hace que sus pruebas sean más legibles. ¿Qué más podrías querer?
Buenas alternativas : Eclipse y Netbeans
El mejor IDE de Java es IntelliJ IDEA. Tiene un montón de características increíbles y es realmente lo principal que hace que la verbosidad de Java sea comprensible. La función de autocompletar es excelente, las inspecciones son de primera categoría y las herramientas de refactorización son realmente útiles.
La edición comunitaria gratuita es bastante buena para mí, pero hay muchas funciones excelentes en la edición Ultimate, como herramientas de bases de datos, compatibilidad con Spring Framework y Chronon.
Una de mis características favoritas de GDB 7 fue la capacidad de viajar en el tiempo durante la depuración. Esto es posible con el complemento Chronon IntelliJ cuando obtienes la edición Ultimate.
Obtienes historial de variables, pasos hacia atrás, historial de métodos y más. Es un poco extraño usarlo la primera vez, pero puede ayudar a depurar algunos errores realmente complejos, Heisenbugs y similares.
Buena alternativa : DCEVM
La integración continua es a menudo un objetivo de los productos de software como servicio. ¿Qué pasaría si ni siquiera tuvieras que esperar a que finalice la compilación para ver los cambios en el código en vivo?
Eso es lo que hace JRebel. Una vez que conecte su servidor a su cliente JRebel, podrá ver los cambios en su servidor al instante. Es un gran ahorro de tiempo cuando se desea experimentar rápidamente.
El sistema de tipos de Java es bastante débil. No diferencia entre cadenas y cadenas que en realidad son expresiones regulares, ni realiza ninguna verificación de contaminación. Sin embargo, Checker Framework hace esto y más.
Utiliza anotaciones como @Nullable para comprobar los tipos. Incluso puede definir sus propias anotaciones para que el análisis estático realizado sea aún más potente.
Incluso siguiendo las mejores prácticas, incluso el mejor desarrollador cometerá errores. Existen varias herramientas que puede utilizar para validar su código Java y detectar problemas en su código. A continuación se muestra una pequeña selección de algunas de las herramientas más populares. Muchos de estos se integran con IDE populares como Eclipse o IntelliJ, lo que le permite detectar errores en su código antes.
Además de utilizar estas herramientas durante el desarrollo, suele ser una buena idea ejecutarlas también durante las etapas de compilación. Se pueden vincular a herramientas de compilación como Maven o Gradle y también a herramientas de integración continua.
Se producen pérdidas de memoria, incluso en Java. Por suerte, existen herramientas para ello. La mejor herramienta que he usado para solucionar estos problemas es Eclipse Memory Analyzer. Se necesita un volcado del montón y le permite encontrar el problema.
Hay algunas formas de obtener un volcado del montón para un proceso JVM, pero yo uso jmap:
$ jmap -dump:live,format=b,file=heapdump.hprof -F 8152
Attaching to process ID 8152, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 23.25-b01
Dumping heap to heapdump.hprof ...
... snip ...
Heap dump file created
Luego puede abrir el archivo heapdump.hprof con el Analizador de memoria y ver qué está pasando rápidamente.
Recursos para ayudarle a convertirse en un maestro de Java.