概述如何redirectJVM输出而不撕裂应用程序的输出?
最近我正在编写一些微基准代码,所以我必须打印出JVM行为以及基准信息。 我用
-XX:+PrintCompilation -XX:+PrintGCDetails
和其他选项来获得JVM状态。 对于基准信息,我只是使用System.out.print()方法。 因为我需要知道我打印的消息和JVM输出的顺序。
当我在控制台中打印出来的时候,我可以得到很好的结果,虽然JVM输出有时会撕掉我的消息,但由于它们在不同的线程中,这是可以理解的和可以接受的。
当我需要做一些批处理基准testing时,我想用pipe (> in linux system) redirect the output into a file pipe (> in linux system) ,并使用python从文件中获得结果并分析它。
如何获得Java Process对象的MemoryUsage统计信息
JAVA应用程序随机崩溃的DLL问题
System.getenv没有得到〜/ .bash_profile中定义的variables
使用JMX和htop报告的Java内存
用java中的空格运行cmd
这是问题:
The JVM output always overlapped with the messages I printed in the Java application. 它毁了消息的完成。
任何想法如何处理这种情况? 我需要both the JVM output and application output in the same place in order to preserve the sequence because it is important. And they do not overlap on each other so I don\’t lose anything. both the JVM output and application output in the same place in order to preserve the sequence because it is important. And they do not overlap on each other so I don\’t lose anything.
在linux中的UTF-8问题
Java:确保一个线程永远不会被上下文切换
试图find泄漏! anon对于pmap意味着什么?
我怎样才能使用Scala的Apachemath?
如何处理ProcessBuilder命令中的编码?
我建议稍微绕行一下,看看使用Java Instrumentation API – 使用(写)一个简单的Java代理来做到这一点。 从你的基准角度来看,这也会给你更多的权力。 您可以使用您的Java代理来记录所有内容(因此不同记录器线程之间不会发生争用)。
你可以阅读更多在http://www.javabeat.net/2012/06/introduction-to-java-agents/或http://today.java.net/pub/a/today/2008/04/24/添加日志记录,以一流的负载时间与- instrumentation.HTML
尝试使用System.out.println()而不是System.out.print() 。 System.out.println()强制刷新syncronized部分内的流,至少你的输出不会混合在一起。
使用Log4J或消息驱动的日志记录框架与System.out.println() 。
Log4J使用消息事件模型来保证消息的排序。 此外,可以使用各种“appender”来登录到数据库或其他输出/文件,从而允许通过Java包和其他属性进行分离,从而不混合数据。
此外,考虑使用高性能定时器和/或不要尝试测量非常短(毫秒)的事件。 原因是调用System.currentTimeMillis()将反过来调用 *** 作系统时钟。 在每个 *** 作系统上都有一些“时钟漂移”和缓存,这样底层的系统功能可能会返回相同的值,导致在实际时间内+/- 30毫秒的偏移量。 为了解决这个问题或提高精度,将被测量的函数分成足够大的样本大小,然后除以迭代次数。
例如,执行平均1-2毫秒的10K *** 作作为一个测量 *** 作。 然后除以10K,以获得每次 *** 作的时间。
否则,再次,一个高性能计时器将是必要的。
通过System.out.print / println直接记录被认为是不好的做法。
为什么?
这不是“线程安全”。 从多个线程记录导致乱码文本
它不灵活,因为它是硬编码的,没有配置。
这是不灵活的,因为你不能指定你想在日志中看到的详细程度(例如详细的跟踪/特定调试逻辑/应用程序警告/应用程序错误处理/应用程序致命错误)。 你总是得到很多,需要注释许多代码行,以避免日志过载。
这是不灵活的,因为你不能指定你或不感兴趣的软件包/类别 – 你总是得到很多东西,并需要评论许多行更简单,更具体
这是不灵活的,因为你不能重定向日志到数据库表和列,文件,电子邮件,消息系统,短信警报等
这是不灵活的,因为你不能将不同的日志级别/包或类传送到不同的日志记录目的地。 另外,您不能将其配置为与应用程序服务器相同的目标或不同的目标,而且它是JVM
当有成千上万条线路被记录到物理磁盘时,速度很慢
2000年,Log4J被引入。
它解决了所有这些问题,并且自那时以来一直是或多或少的标准解决方案。 虽然有一些最新的和最好的日志记录工具试图超越Log4J,但您仍然可以使用Log4J获得强大而灵活的结果。 如果你把所有的System.out.print调用切换到Log4J,那么你引用的问题和其他许多问题将会消失。
http://logging.apache.org/log4j/1.2/manual.HTML
对于-XX:+PrintCompilation ,您可以使用-XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation标志来获得单独的“hotspot.log”文件中的“详细”输出。 该文件采用XML格式,包含-XX:+PrintCompilation的信息以及这种编译的原因。 文件路径可以通过-XX:Logfile=<new_hotspot_log>进行更改。 参考: https : //wikis.oracle.com/display/HotSpotInternals/LogCompilation+overvIEw
对于-XX:+PrintGCDetails ,可以使用-Xloggc:<gc_log>将GC输出重定向到指定的文件。 参考: java -X
我会建议尝试以下。 这是更多的黑客,并需要一些修补。 但掌握这种方法可能会长期得到回报。 特别是,如果你做了很多基准。
话虽如此,我认为HS(现在,甲骨文)应该有一个选项来重定向编译器输出到一个文件。 你只需要足够的努力:-) HS应该有一个选项来打印出所有的JVM和编译器选项,其中可能是将输出重定向到一个文件的选项。
无论如何,我离题了…
1)$ JAVA_HOME或%JAVA_HOME%中应该有src.zip。 它包含java类库的源代码。
2)修改System.out将所有输出重定向到一个特定的失败,或者简单地插入一些特殊的符号,你可以grep捕获stdout和stderr。 不幸的是,由于我们公司的政策禁止我们检查src.zip的内容,所以我不能更具体地说明这一步骤。 我只能想象这一步会有多困难。 也许和输出流交换出来一样简单,或者像修改应用程序直接使用的每一种打印方法一样困难。 我甚至不知道有多少本地的System.out使用
3)把你的编译版本放在一个jar文件中。
4)将此选项添加到您的命令行:-Xbootclasspath / p:full_path_to_your_jar这将告诉JVM首先使用您的类的版本。 “P”代表前置。
希望这有助于…
首先,我会尝试@barracel关于使用System.out.println()的注意事项。
我不太了解Java,但是您也可以将所有调试消息写出到stderr,并留下JVM的stdout。 这可以防止当多个线程写入相同的文件描述符时显然发生的stdout污染。
尝试拆分JVM和您的应用程序的输出。
将JVM的信息输出到标准输出
用“System.err.println()”输出应用程序的信息到stderr
用你最喜欢的工具分析输出。
所以,命令行是这样的:
$java -XX:+PrintCompilation -XX:+PrintGCDetails MainClass 1>stdout.txt 2>stderr.txt
为了以非重叠的方式输出,使用System.out.println。 那么你可以重定向到像这样的文件:
java -XX:+PrintCompilation -XX:+PrintGCDetails MainClass 1>stdout.txt 2>&1
这是所有错误以及在文件名stdout.txt中的正常控制台输出
另外,如果日志有任何形式的线程/时间信息,您可以简单地使用
sort -n -k 1
其中-k 1表示具有线程/数据(epoch)信息的列。
总结
以上是内存溢出为你收集整理的如何redirectJVM输出而不撕裂应用程序的输出?全部内容,希望文章能够帮你解决如何redirectJVM输出而不撕裂应用程序的输出?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
请登录后查看评论内容