Soru JVM çıkışını uygulamadan koparmadan nasıl yönlendirilir?


Son zamanlarda bazı mikro kriter kodları yazıyor, bu yüzden JVM davranışlarım, karşılaştırma bilgilerim ile birlikte yazdırmam gerekiyor. kullanırım

-XX:+PrintCompilation
-XX:+PrintGCDetails

ve JVM durumunu almak için diğer seçenekler. Karşılaştırma bilgisi için kullanıyorum System.out.print() yöntem. Çünkü yazdırdığım mesajın sırasını ve JVM çıkışını bilmem gerekiyor.

JVM çıktısı bazen mesajlarımı yırtıp almasına rağmen konsolda yazdırdığımda iyi sonuç alabiliyorum, ancak farklı iş parçacıklarına sahip olduklarından anlaşılabilir ve kabul edilebilir.

Bazı parti kriterleri yapmam gerektiğinde, redirect the output into a file ile pipe (> in Linux system)ve dosyadan sonuca ulaşmak ve analiz etmek için python'u kullanın.

İşte problem:

The JVM output always overlapped with the messages I printed in the Java application. Mesajların tamamlanmasını mahvetti.

Bu durumla nasıl baş edileceğine dair bir fikrin var mı? ihtiyacım var 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.


18
2017-11-18 01:09


Menşei




Cevaplar:


Hafif bir sapma almayı ve Java Instrumentation API'lerini kullanmayı öneririm - kullanımı (yaz) basit Java Aracısı Bunu yapmak için. Kıyaslama bakış açınızdan, bu size çok daha fazla güç verecektir. Java Agent'ınızı her şeyi günlüğe kaydetmek için kullanabilirsiniz (ve dolayısıyla farklı logger iş parçacıkları arasında bir çekişme olmayacaktır).

Daha fazla okuyabilirsiniz http://www.javabeat.net/2012/06/introduction-to-java-agents/ veya http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html


9
2017-11-18 02:09



İyi fikir, ajandaki stdout ve stderr'i yeniden yönlendirmeyi denedim, çıktıyı java kodumdan yönlendirebilirim, fakat JVM çıkışı yeniden yönlendirilmez. Ve bahsettiğiniz makalede tanıtılan yöntem - sınıfı yüklerken bayt kodunu değiştirirseniz, bilgi çıktığında JVM'nin ne çağırdığını bilmek zorundayım, sonra belki de onu değiştirebilirim, ama bu tür bilgi, herhangi bir öneriniz var mı? - dawnstar


Kullanmayı deneyin System.out.println() yerine System.out.print(). System.out.println() Senkronize bölüm içinde bir akışı akıtmaya zorlar ve en azından çıktınız karma kadar olmayacaktır.


5
2018-02-19 16:13





Log4J veya mesaja dayalı kayıt çerçevesini kullanın System.out.println().

Log4J, mesajların siparişini garantileyen bir mesaj olay modeli kullanır. Ayrıca, çeşitli “ekleyiciler” bir veri tabanına veya başka bir çıktıya / dosyaya giriş yapmak için kullanılabilir, böylece Java paketi ve diğer özellikler ayrılarak veri karıştırılmaz.

Ayrıca, bu satırlar boyunca, yüksek performanslı bir zamanlayıcı kullanmayı düşünün ve / veya çok kısa (milisaniye) olayları ölçmeye çalışmayın. Nedeni, bir çağrı System.currentTimeMillis() sadece işletim sistemi saatini arayacaktır. Her işletim sisteminde, bir 'saat kayması' ve önbellek sistemi işlevi, altta yatan sistem işlevi aynı değeri döndürerek, gerçek zamanda +/- 30 ms'lik sapmalara neden olacak şekilde devam eder. Bunu düzeltmek veya doğruluğu arttırmak için ölçülen işlevleri yeterince büyük bir örneklem büyüklüğünde gruplandırın ve daha sonra yineleme sayısına bölün.

Örneğin, ölçülen bir işlem olarak 1-2 milisaniyede ortalama olan 10K işlemlerini gerçekleştirin. Daha sonra işlem başına almak için 10K'ya bölün.

Aksi takdirde, yine yüksek performanslı bir zamanlayıcı gerekli olacaktır.


5
2018-02-21 23:07



Bu orijinal soruya cevap vermiyor. Log4J, HotSpot tanılama kayıt defterlerinde veya uygulama çıktılarıyla aynı dosyada aralarındaki ilişkiyi geçici ilişkilerini yansıtacak şekilde ayırma konusunda yardımcı olmaz. - Per Mildner
HotSpot tanılama, söz konusu değildi. Soru, üst üste gelmeden kayıt sırasının nasıl korunacağıydı ve çözüm kesinlikle bunu yapmanın bir yoludur. - Darrell Teague
Soruyu (okuduğumda, düzenlenmiş), HotSpot tanılamalarını -XX: + PrintCompilation ve ilk paragrafta diğer kayıtlarla doğru şekilde düzenleme gereğinden bahseder. - Per Mildner


System.out.print / println ile doğrudan oturum açmak zayıf uygulama olarak kabul edilir.

Niye ya?

  1. Bu 'iplik güvenli' değil. Birden çok ileti dizisinden günlüğe kaydetme, bozuk metinle sonuçlanır
  2. Esnek değildir, çünkü kodlanmış ve yapılandırılmamış.
  3. Esnek değildir çünkü günlüğünde görmek istediğiniz ayrıntı düzeyini belirleyemezsiniz (örneğin ayrıntılı izleme / belirli hata ayıklama mantığı / uygulama uyarıları / uygulama hatası işleme / uygulama ölümcül hataları). Her zaman çok şey alırsınız ve aşırı yüklemeyi önlemek için birçok kod satırına yorum yapmanız gerekir.
  4. Esnek değildir, çünkü hangi paketlerin / sınıfların ilginizi çekmediğini ya da ilginizi çekmediğini belirleyemezsiniz - tekrar her zaman çok şey elde edersiniz ve daha basit ve daha belirgin bir şey için birçok satırı yorumlamanız gerekir.
  5. Bu esnek değildir, çünkü veritabanı tablolarına ve sütunlarına, dosyalara, e-postalara, mesaj sistemlerine, SMS uyarılarına vb.
  6. Esnek değildir, çünkü farklı günlük düzeylerini / paketlerini veya sınıflarını farklı günlük hedeflerine aktaramazsınız. Ayrıca, aynı hedefe veya uygulama sunucusu olarak farklı bir hedefe ve JVM'ye giriş yapacak şekilde yapılandıramazsınız.
  7. Fiziksel diske binlerce / milyonlarca satır kaydedilirken yavaştır

2000 yılında Log4J tanıtıldı.
Tüm bu sorunlara hitap ediyor ve o zamandan beri standart çözümden çok ya da çok fazla. Log4J'in ötesine geçmeye çalışan en yeni ve en büyük kayıt araçları olsa da, Log4J ile güçlü ve esnek sonuçlar elde edebilirsiniz. Tüm System.out.print çağrılarınızı Log4J'ye değiştirirseniz, söz konusu sorun ve diğer pek çok sorun ortadan kalkacaktır.

http://logging.apache.org/log4j/1.2/manual.html


4
2018-02-22 14:22





İçin -XX:+PrintCompilation, kullanabilirsin -XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation Bunun yerine ayrı "hotspot.log" dosyasında "verbose" çıktısı almak için bayraklar. Bu dosya XML biçimindedir ve her iki -XX:+PrintCompilation ve bu tür derlemelerin nedeni. Dosya yolu üzerinden değiştirilebilir -XX:LogFile=<new_hotspot_log>. Referans: https://wikis.oracle.com/display/HotSpotInternals/LogCompilation+overview

İçin -XX:+PrintGCDetails, kullanabilirsin -Xloggc:<gc_log> GC çıktısını belirtilen dosyaya yönlendirmek için. Referans: java -X


2
2017-10-11 03:18





Aşağıdakileri denemenizi tavsiye ederim. Bu bir hack daha ve biraz tinkering gerektirecektir. Fakat bu yaklaşıma hakim olmak muhtemelen uzun vadede ödeyecek. Özellikle, çok fazla kıyaslama yaparsanız.

HS'nin (günümüzde Oracle) derleyici çıktısını bir dosyaya yeniden yönlendirmek için bir seçeneğe sahip olması gerektiğine dair olumlu olduğumu söylemiştim. Sadece onu yeterince zor bulmaya ihtiyacınız var :-) HS, tüm JVM ve derleyici seçeneklerini basma seçeneğine sahip olmalı ve aralarında çıktıyı bir dosyaya yönlendiren tek seçenek olabilir.

Her neyse, ben ...

1) $ JAVA_HOME veya% JAVA_HOME% oranında src.zip olmalıdır. Java Sınıf Kitaplığı için kaynak kodunu içerir.

2) Tüm çıkışı belirli bir hataya yönlendirmek için System.out'u değiştirin ya da stdout ve stderr'i yakalamak için grep yapabileceğiniz bazı özel semboller ekleyin. Maalesef, şirketimizin politikası, src.zip'in içeriğini incelememizi yasakladığı için, bu özel adımla daha spesifik olamam. Bu adımın ne kadar zor olacağını hayal edebiliyorum. Belki de çıktı akışınızla "dışarıda" takas etmek veya uygulamanızın doğrudan kullandığı her baskı yöntemini değiştirmek kadar zor olabilir. System.out'un kaç yerli olduğunu bile bilmiyorum.

3) Derlenmiş sürümünüzü bir jar dosyasına koyun.

4) Bu seçeneği komut satırınıza ekleyin: -Xbootclasspath / p: full_path_to_your_jar Bu, JVM'ye sınıfınızın ilk sürümünü kullanmasını söyleyecektir. "P", prepend anlamına gelir.

Umarım bu yardımcı olur ...


0
2017-11-18 06:11





Öncelikle, System.out.println () 'in kullanımıyla ilgili @barracel'in ne denediğini deneyebilirim.

Java hakkında fazla bir şey bilmiyorum, ancak tüm hata ayıklama mesajlarınızı stderr'e yazıp JVM için stdout'u bırakabilirsiniz. Bu, birden fazla iş parçacığının aynı dosya tanıtıcısına yazdığı zaman görünen stdout kirliliğini önleyebilir.


0
2018-02-19 20:24





JVM'nin çıkışını ve uygulamanızı bölmeyi deneyin.

  • JVM'nin bilgilerini stdout'a iletme
  • Uygulamanızın bilgilerini "System.err.println ()" ile stderr'e aktarın.
  • Çıkışı favori araçlarınızla analiz edin.

Yani, komut satırı şöyle:

$java -XX:+PrintCompilation -XX:+PrintGCDetails MainClass 1>stdout.txt 2>stderr.txt

0
2018-02-21 06:03





Çıkışı çakışmayan moda sahip olmak için System.out.println dosyasını kullanın. Sonra, aynı dosyaya şu şekilde yönlendirme yapabilirsiniz:

java -XX:+PrintCompilation -XX:+PrintGCDetails MainClass 1>stdout.txt 2>&1

Bu, stdout.txt dosya adındaki normal konsol çıktılarının yanı sıra tüm hatayı da içerir.

Ayrıca, günlükler herhangi bir iplik / zaman bilgisine sahipse, sadece

sort -n -k 1

Burada -k 1, iş parçacığı / veri (epoch) bilgisine sahip olduğunuz sütun için durur.


0
2018-02-23 05:56