{"id":894,"date":"2012-10-09T11:10:10","date_gmt":"2012-10-09T16:10:10","guid":{"rendered":"http:\/\/alejandroayala.solmedia.ec\/?p=894"},"modified":"2012-10-09T11:15:24","modified_gmt":"2012-10-09T16:15:24","slug":"comandos-linux-utiles-para-depurar-el-rendimiento-de-aplicaciones-java","status":"publish","type":"post","link":"https:\/\/alejandroayala.solmedia.ec\/?p=894","title":{"rendered":"Comandos linux \u00fatiles para depurar el rendimiento de aplicaciones Java"},"content":{"rendered":"<p style=\"text-align: justify;\">Linux es un sistema operativo muy bueno, si nosotros\u00a0conoci\u00e9ramos\u00a0las herramientas correctas para <em>\u00abdebugear\u00bb<\/em> <strong>nuestra tarea ser\u00eda mas\u00a0f\u00e1cil<\/strong>. Algunas veces es <strong>bastante\u00a0dif\u00edcil\u00a0encontrar los errores en sistemas<\/strong> que ya han salido a producci\u00f3n, a continuaci\u00f3n se detalle algunos comandos que har\u00e1n que depurar aplicaciones java sobre sistemas opertivos linux sea mas f\u00e1cil.<\/p>\n<p style=\"text-align: justify;\"><!--more--><\/p>\n<h2 style=\"text-align: justify;\"><strong>1. lsof. Comprueba si existen <a href=\"http:\/\/en.wikipedia.org\/wiki\/File_descriptor\" target=\"_blank\">descriptores de archivos<\/a> abiertos.<\/strong><\/h2>\n<p style=\"text-align: justify;\">Este comando lista los <strong>descriptores de archivos abiertos<\/strong> por un proceso de un sistema Unix. A continuaci\u00f3n una breve descripci\u00f3n de la salida del comando man de <em><strong>lsof<\/strong><\/em>.<\/p>\n<blockquote>\n<p style=\"text-align: justify;\">An open file may be a regular file, a directory, a block special file, a character special file, an executing text \u00a0reference, a library, a stream or a network\u00a0file (Internet socket, NFS file or UNIX domain socket.) A specific file or all the files in a file system may be selected by path.<\/p>\n<\/blockquote>\n<p style=\"text-align: justify;\">Este comando es bastante\u00a0\u00fatil\u00a0cuando te enfrentas a problemas relacionados con librer\u00edas de terceros y resulta complicado distinguir cual librer\u00eda est\u00e1 usando tu programa. La salida del comando muestra <strong>la ruta absoluta de las\u00a0librer\u00edas\u00a0que est\u00e1n abiertas<\/strong>. De echo es muy interesante ver que muchas de las librer\u00edas no han sido cargadas hasta que tu aplicaci\u00f3n las necesita. Un ejemplo de la salida del comando <em><strong>lsof<\/strong> <\/em>se muestra a continuaci\u00f3n:<\/p>\n<p>[bash]<br \/>\n$ lsof -p 4485<br \/>\njava 4485 alejo 22r REG 8,4 907988 1576751 $JBOSS_HOME\/server\/default\/lib\/jboss-remoting.jar<\/p>\n<p>java 4485 alejo 23r REG 8,4 4018512 1576724 $JBOSS_HOME\/server\/default\/lib\/richfaces-ui.jar<br \/>\njava 4485 alejo 24r REG 8,4 65046 1576776 $JBOSS_HOME\/server\/default\/lib\/jboss-jsr88.jar<br \/>\njava 4485 alejo 25r REG 8,4 3539 1576774 $JBOSS_HOME\/server\/default\/lib\/scheduler-plugin-example.jar<br \/>\njava 4485 alejo 26r REG 8,4 111591 1576760 $JBOSS_HOME\/server\/default\/lib\/hibernate-entitymanager.jar<br \/>\njava 4485 alejo 27r REG 8,4 15146 1576794 $JBOSS_HOME\/server\/default\/lib\/log4j-snmp-appender.jar<br \/>\njava 4485 alejo 28r REG 8,4 398781 1576717 $JBOSS_HOME\/server\/default\/lib\/alfresco-web-service-client.jar<br \/>\njava 4485 alejo 29r REG 8,4 1516943 1576738 $JBOSS_HOME\/server\/default\/lib\/richfaces-impl.jar<br \/>\njava 4485 alejo 30r REG 8,4 599743 1576735 $JBOSS_HOME\/server\/default\/lib\/javassist.jar<br \/>\njava 4485 alejo 31r REG 8,4 167694 1576746 $JBOSS_HOME\/server\/default\/lib\/bsf.jar<br \/>\njava 4485 alejo 32r REG 8,4 65358 1576775 $JBOSS_HOME\/server\/default\/lib\/jbossws-common.jar<br \/>\njava 4485 alejo 33r REG 8,4 55424 1576722 $JBOSS_HOME\/server\/default\/lib\/commons-logging.jar<br \/>\n[\/bash]<\/p>\n<h4 style=\"text-align: justify;\">\u00bfC\u00f3mo usarlo?<\/h4>\n<p style=\"text-align: justify;\">Si nos fijamos en la salida anterior, este comando muestra<strong> detalles exactos de los archivos abiertos por tu aplicaci\u00f3n<\/strong>. Si hay un <em>jar<\/em> que no corresponde a los usados por el programa, puedes descubrir f\u00e1cilmente cual es mirando su ruta absoluta.<\/p>\n<p style=\"text-align: justify;\"><strong>Nota:<\/strong> La salida ha sido modificada, en la ruta de las librer\u00edas por seguridad. Para saber el proceso java que esta asignado usamos la siguiente orden: ps -ef | grep java . La segunda columna es el PID.<\/p>\n<h2 style=\"text-align: justify;\">2. pstack. Comprueba si existen procesos \u00abstack trace\u00bb<\/h2>\n<p style=\"text-align: justify;\">Este comando es ralmente muy \u00fatil si esta depurando algunos<strong> errores cr\u00edticos como deadlock en producci\u00f3n<\/strong>. A continuaci\u00f3n de la salida del comando pstack para un proceso java.<\/p>\n<p>[bash]<br \/>\n$ pstack 4485<\/p>\n<p>Thread 209 (Thread 818031520 (LWP 26203)):<br \/>\n#0 0xb7fe87a2 in _dl_sysinfo_int80 () from \/lib\/ld-linux.so.2<br \/>\n#1 0xb7fd3f7c in pthread_cond_timedwait@@GLIBC_2.3.2 ()<br \/>\n#2 0xb7fd43f5 in pthread_cond_timedwait@GLIBC_2.0 ()<br \/>\n#3 0xb78ee95c in os::Linux::safe_cond_timedwait ()<br \/>\n#4 0xb78d5e41 in Monitor::wait ()<br \/>\n#5 0xb79d1e8b in VMThread::loop ()<br \/>\n#6 0xb79d1af0 in VMThread::run ()<br \/>\n#7 0xb78ef6f8 in _start ()<br \/>\n#8 0xb7fd13cc in start_thread () from \/lib\/tls\/libpthread.so.0<br \/>\n#9 0xb7f6396e in clone () from \/lib\/tls\/libc.so.6<br \/>\n[\/bash]<\/p>\n<h4 style=\"text-align: justify;\">\u00bfC\u00f3mo usarlo?<\/h4>\n<p style=\"text-align: justify;\">Este comando es bastante \u00fatil en el caso en que se est\u00e9 depurando un<strong> programa java con m\u00faltiples hilos<\/strong>. Al depurar errores que tienen que ver con consumo de CPU, este comando es de bastante ayuda, se puede comprobar que al tener demasiados procesos haciendo uso del CPU\u00a0habr\u00e1\u00a0muchos mas que se quedaron a la espera.<\/p>\n<h2 style=\"text-align: justify;\">3.\u00a0jstack &#8211; Hilos de procesos java stack trace.<\/h2>\n<p style=\"text-align: justify;\">Este comando es bastante \u00fatil cuando estas depurando <strong>errores dificiles de reproducir<\/strong>, como deadlocks, uso exesivo de CPU, etc.\u00a0A continuaci\u00f3n de la salida del comando jstack\u00a0para un proceso java usando el comando jstack.<\/p>\n<p>[bash]<br \/>\nAttaching to process ID 24776, please wait&#8230;<\/p>\n<p>Debugger attached successfully.<br \/>\nServer compiler detected.<br \/>\nJVM version is 1.5.0_16-b02<br \/>\nThread 25010: (state = IN_NATIVE)<br \/>\n&#8211; java.net.SocketInputStream.socketRead0(java.io.FileDescriptor, byte[], int, int, int) @bci=0 (Compiled frame; information may be imprecise)<br \/>\n&#8211; java.net.SocketInputStream.read(byte[], int, int) @bci=84, line=129 (Compiled frame)<br \/>\n&#8211; com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(com.sun.net.ssl.internal.ssl.InputRecord, boolean) @bci=44, line=782 (Interpreted frame)<br \/>\n&#8211; com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(com.sun.net.ssl.internal.ssl.InputRecord) @bci=15, line=739 (Interpreted frame)<br \/>\n&#8211; com.sun.net.ssl.internal.ssl.AppInputStream.read(byte[], int, int) @bci=30, line=75 (Interpreted frame)<br \/>\n&#8211; org.apache.coyote.http11.InternalInputBuffer.fill() @bci=59, line=738 (Interpreted frame)<br \/>\n&#8211; org.apache.coyote.http11.InternalInputBuffer.parseRequestLine() @bci=16, line=399 (Compiled frame)<br \/>\n&#8211; org.apache.coyote.http11.Http11Processor.process(java.io.InputStream, java.io.OutputStream) @bci=327, line=828 (Compiled frame)<br \/>\n[\/bash]<\/p>\n<h4 style=\"text-align: justify;\">\u00bfC\u00f3mo usarlo?<\/h4>\n<p style=\"text-align: justify;\">Este comando es bastante \u00fatil ya que te permite saber <strong>exactamente el nombre de la \u00a0clase o del m\u00e9todo<\/strong> como una traza de error. Si est\u00e1s depurando el uso excesivo de CPU, toma dos o tres capturas de este log y revisa que m\u00e9todo o clase se repite en cada captura y el hilo que se est\u00e1 comiendo mas ciclos de la CPU.<\/p>\n<h2 style=\"text-align: justify;\">4. ps con la opci\u00f3n \u00ab-L\u00bb<\/h2>\n<p style=\"text-align: justify;\">Este comando es bastante usado, m\u00e1s no su opci\u00f3n -L. Esta opci\u00f3n lista los procesos mas \u00abligeros\u00bb de un sistema operativo Linux. La salida de este comando puede ser combinado con la salida del comando\u00a0jstack para <strong>un an\u00e1lisis m\u00e1s detallado<\/strong>.\u00a0A continuaci\u00f3n de la salida simple del comando ps -L.<\/p>\n<p>[bash]<br \/>\nps -aefL | grep java | more<br \/>\nhost 10258 1 10258 0 94 Dec23 ? 00:00:25 \/usr\/java\/jdk\/bin\/java -Xms1024M -Xmx1536M -XX:-UseParallelGC -Djava.util.logging.manager=org.apac<br \/>\nhe.juli.ClassLoaderLogManager -Djava.util.logging.config.file=\/usr\/local\/tomcat\/conf\/logging.properties -Djava.endorsed.dirs=\/usr\/local\/tomcat\/common\/endorse<br \/>\nd -classpath :\/usr\/local\/tomcat\/bin\/bootstrap.jar:\/usr\/local\/tomcat\/bin\/commons-logging-api.jar -Dcatalina.base=\/usr\/local\/tomcat -Dcatalina.home=\/usr\/local\/<br \/>\ntomcat -Djava.io.tmpdir=\/usr\/local\/tomcat\/temp org.apache.catalina.startup.Bootstrap start<br \/>\nhost 10258 1 10259 0 94 Dec23 ? 00:03:15 \/usr\/java\/jdk\/bin\/java -Xms1024M -Xmx1536M -XX:-UseParallelGC -Djava.util.logging.manager=org.apac<br \/>\nhe.juli.ClassLoaderLogManager -Djava.util.logging.config.file=\/usr\/local\/tomcat\/conf\/logging.properties -Djava.endorsed.dirs=\/usr\/local\/tomcat\/common\/endorse<br \/>\nd -classpath :\/usr\/local\/tomcat\/bin\/bootstrap.jar:\/usr\/local\/tomcat\/bin\/commons-logging-api.jar -Dcatalina.base=\/usr\/local\/tomcat -Dcatalina.home=\/usr\/local\/<br \/>\ntomcat -Djava.io.tmpdir=\/usr\/local\/tomcat\/temp org.apache.catalina.startup.Bootstrap start<br \/>\n[\/bash]<\/p>\n<h4 style=\"text-align: justify;\">\u00bfC\u00f3mo usarlo?<\/h4>\n<p style=\"text-align: justify;\">Este comando puede ser usando en <strong>combinaci\u00f3n de los comandos\u00a0\u00a0<em>pstack<\/em> &amp; <em>jstack<\/em><\/strong>. Los comandos <strong><em>pstack<\/em><\/strong> y <strong><em>jstack<\/em> <\/strong>usan el ID del hilo del proceso en su salida y usando el comando \u00abps -L\u00bb se puede ver los procesos ligeros (hilos unix) para tu proceso java. Esto puede ayudarte a apuntar al hilo exacto que est\u00e1 causando problemas.<\/p>\n<h2 style=\"text-align: justify;\">5. jmap &#8211; Controlar la asignaci\u00f3n de almacenamiento din\u00e1mico de Java<\/h2>\n<p style=\"text-align: justify;\">El comando jmap es parte del JDK 5, puede ser usado para conectarse a un proceso java \u00abvivo\u00bb. Al igual que el comando jstack este comando se puede usar en procesos que ya est\u00e1n corriendo para <strong>obtener los detalles del uso de memoria<\/strong>(detalles de la asignacion de la JVM). El uso de este comando es: jpam [pid]. A continuaci\u00f3n la salida de este comando.<\/p>\n<p>[bash]<br \/>\n$ \/usr\/java\/jdk\/bin\/jmap 4485<br \/>\nAttaching to process ID 4485, please wait&#8230;<br \/>\nDebugger attached successfully.<br \/>\nServer compiler detected.<br \/>\nJVM version is 1.5.0_16-b02<br \/>\n0x08048000 62K \/usr\/java\/jdk1.5.0_16\/bin\/java<br \/>\n0x477ae000 343K \/usr\/java\/jdk1.5.0_16\/jre\/lib\/i386\/libcmm.so<br \/>\n0x4923b000 77K \/lib\/libresolv-2.3.4.so<br \/>\n0x4924e000 21K \/lib\/libnss_dns-2.3.4.so<br \/>\n0x49257000 22K \/usr\/java\/jdk1.5.0_16\/jre\/lib\/i386\/libmanagement.so<br \/>\n0x4b9ed000 71K \/usr\/java\/jdk1.5.0_16\/jre\/lib\/i386\/libnet.so<br \/>\n0x4c310000 156K \/usr\/java\/jdk1.5.0_16\/jre\/lib\/i386\/libjpeg.so<br \/>\n0xb741e000 63K \/usr\/java\/jdk1.5.0_16\/jre\/lib\/i386\/libzip.so<br \/>\n0xb742f000 133K \/usr\/java\/jdk1.5.0_16\/jre\/lib\/i386\/libjava.so<br \/>\n0xb7452000 47K \/usr\/java\/jdk1.5.0_16\/jre\/lib\/i386\/libverify.so<br \/>\n0xb745e000 46K \/lib\/libnss_files-2.3.4.so<br \/>\n0xb7469000 97K \/lib\/libnsl-2.3.4.so<br \/>\n0xb748a000 206K \/lib\/tls\/libm-2.3.4.so<br \/>\n0xb74ae000 26K \/usr\/java\/jdk1.5.0_16\/jre\/lib\/i386\/native_threads\/libhpi.so<br \/>\n0xb74b7000 7275K \/usr\/java\/jdk1.5.0_16\/jre\/lib\/i386\/server\/libjvm.so<br \/>\n0xb7e98000 1502K \/lib\/tls\/libc-2.3.4.so<br \/>\n0xb7fc7000 14K \/lib\/libdl-2.3.4.so<br \/>\n0xb7fcc000 103K \/lib\/tls\/libpthread-2.3.4.so<br \/>\n0xb7fe8000 108K \/lib\/ld-2.3.4.so<br \/>\n[\/bash]<\/p>\n<h4 style=\"text-align: justify;\">\u00bfC\u00f3mo usarlo?<\/h4>\n<p style=\"text-align: justify;\">Este comando es bastante \u00fatil al depurar \u00abissues\u00bb en <strong>procesos java\u00a0OutOfMemory<\/strong>. Para m\u00e1s detalles referir a los comandos del JDK en el siguiente enlace.\u00a0<a href=\"http:\/\/www.oracle.com\/technetwork\/java\/javase\/index-138283.html\">Troubleshooting Java SE<\/a>.<\/p>\n<p style=\"text-align: justify;\">En PID(ID del proceso) usado para los ejemplos(4485) es el id del proceso de mi m\u00e1quina. Para saber cual es id del proceso java de tu m\u00e1quina puedes emplear el siguiente comando:<\/p>\n<p>[bash]<br \/>\n$ ps -ef \u00a0| \u00a0grep java<br \/>\n[\/bash]<\/p>\n<p>Para m\u00e1s informaci\u00f3n y detalles referir a la fuente:\u00a0<a href=\"http:\/\/www.fromdev.com\/2008\/12\/debugging-java-on-unixlinux-my-favorite.html\">http:\/\/www.fromdev.com\/2008\/12\/debugging-java-on-unixlinux-my-favorite.html<\/a><\/p>\n\n<div class=\"twitter-share\"><a href=\"https:\/\/twitter.com\/intent\/tweet?via=a1ejo_ayala\" class=\"twitter-share-button\" data-size=\"large\">Twittear<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Linux es un sistema operativo muy bueno, si nosotros\u00a0conoci\u00e9ramos\u00a0las herramientas correctas para \u00abdebugear\u00bb nuestra tarea ser\u00eda mas\u00a0f\u00e1cil. Algunas veces es bastante\u00a0dif\u00edcil\u00a0encontrar los errores en sistemas que ya han salido a producci\u00f3n, a continuaci\u00f3n se detalle algunos comandos que har\u00e1n que depurar aplicaciones java sobre sistemas opertivos linux sea mas f\u00e1cil.<\/p>\n","protected":false},"author":1,"featured_media":690,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[4],"tags":[141,201,200,29,202,506,47,199,198],"_links":{"self":[{"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=\/wp\/v2\/posts\/894"}],"collection":[{"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=894"}],"version-history":[{"count":12,"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=\/wp\/v2\/posts\/894\/revisions"}],"predecessor-version":[{"id":943,"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=\/wp\/v2\/posts\/894\/revisions\/943"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=\/wp\/v2\/media\/690"}],"wp:attachment":[{"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=894"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=894"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=894"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}