जावा एप्लिकेशन को डीबग करना जब यह बिल्कुल भी प्रतीक्षा नहीं कर रहा है - इनट्रेस दृष्टिकोण में आपका स्वागत है

क्या आपने कभी कुछ जावा कोड के निष्पादन के लिए कदम दर कदम अध्ययन किया है जो आपने लॉगिंग टूल या अन्य निगरानी तंत्र से लैस करने के लिए परेशान नहीं किया है?
हम कार्य को इस तथ्य से जटिल करते हैं कि हम अध्ययन के तहत कोड को फिर से नहीं जमा करेंगे, और वास्तव में मौजूदा प्रक्रिया को फिर से शुरू करेंगे (मामला जब अक्षम्य व्यवहार फिर से शुरू होने पर भी चल रहा था)। जावा मशीन, निश्चित रूप से, सबसे आम विकल्पों (डीबगर अनुलग्नक या कुछ अन्य घंटियाँ और सीटी बजाने के मापदंडों के बिना) के साथ लॉन्च की गई है।
और मैं समझना चाहता हूं कि क्या हो रहा है।

वही हम करेंगे।

एक उदाहरण के लिए, आइए एक सरल कोड लें, जो पुराने प्रसिद्ध प्रसिद्ध कथा "शलजम" के कार्यान्वयन का कुछ हिस्सा है। नीचे दिए गए कोड के प्रदर्शन का उद्देश्य कक्षाओं या विधियों के आयोजन की सुंदरता को दिखाना नहीं है, अकेले नामकरण (यहां, बल्कि, अपमान) दें, लेकिन बस कॉल के बाद कॉल की एक श्रृंखला बनाने के लिए।

1: package skazka; 2: 3: import java.io.BufferedReader; 4: import java.io.InputStreamReader; 5: 6: public class Repka { 7: public static void main(String[] args) throws Exception { 8: new BufferedReader(new InputStreamReader(System.in)).readLine(); 9: 10: try { 11: new Dedka().tyanem("", 200); 12: } catch (Exception ex) { 13: processError(ex); 14: } 15: 16: } 17: 18: public static boolean processError(Exception ex) { 19: // ... 20: return true; 21: } 22: } 23: 24: class Dedka { 25: void tyanem(String target, int weight) { 26: new Babka().tyanem(target, weight - 15); 27: } 28: } 29: 30: class Babka { 31: void tyanem(String target, int weight) { 32: new Vorona().tyanem(target, weight - 10); 33: } 34: } 35: 36: class Vorona { 37: void tyanem(String target, int weight) { 38: if (!target.equals("")) { 39: throw new RuntimeException("    "); 40: } 41: 42: // ... 43: } 44: } 


संकलन

 javac skazka/Repka.java 

और दौड़ो

 java skazka.Repka 


अब आपको पहले से ही चल रही प्रक्रिया में किसी तरह "वेज" करने और अपनी आवश्यकताओं के लिए कोड को अनुकूलित करने की आवश्यकता है। मार्टिन रॉबर्टसन (जिसके लिए कई, कई ईमानदारी से धन्यवाद) द्वारा बनाया गया जावा एजेंट, इनट्रेस mchr3k.imtqy.com/org.intrace कहा जाता है, इसके लिए पूरी तरह से अनुकूल है , यह इसे मक्खी पर निष्पादन योग्य कोड में एम्बेड करने की अनुमति देता है, इसे ट्रेसिंग तत्व प्रदान करता है।

InTrace एजेंट को पहले से चल रहे जावा प्रक्रिया में सरल तरीकों से एक जोड़े में रखा गया है (चुनने के लिए):
1) सॉफ्टवेयर विधि
 public static void loadAgent(String pid, String agentFilePath) throws Exception { VirtualMachine vm = VirtualMachine.attach(pid); vm.loadAgent(agentFilePath, ""); vm.detach(); } 


Java एजेंट intrace-agent.jar प्रक्रिया को github.com/mchr3k/org.intrace/tree/master/binaries/jars/latest_development से खिसकाना

2) विजुअलवीएम लेना (डाउनलोड करना, अगर यहां से कोई विजुअवम.जवा.नेट नहीं है) और इसे पैच करना (टूल-> प्लगइन्स) इनट्रेस-इन्ट्रेस-विजुव्म.एनबीएम प्लगइन से लिया गया
github.com/mchr3k/org.intrace/tree/master/binaries/jars/latest_development

मुसीबत यह है कि org-intrace-visualvm.nbm नवीनतम फाइलें नहीं हैं, इसलिए विज़ुअल वीएम प्लगइन्स को स्टोर करता है और संबंधित dzharniki को github.com/mchr3k/org.intrace/tree/master/binaries/jars/jars से हाल के अन्य में बदलें। latest_development
मेरे मामले में (लिनक्स ओएस), मुझे प्रतिस्थापित करना चाहिए था
intrace-agent.jar पर intrace-agent.jar और intrace-client-gui-linux.jar पर इंट्रेस- ui.jar (नीचे स्क्रीनशॉट देखें, प्लगइन रास्ता बताता है)

अब यह VisualVM शुरू करने के लिए बना हुआ है, skazka.Repka के लिए संदर्भ मेनू पर कॉल करें और "इनट्रेस एप्लिकेशन ..." चुनें, जिसके बाद हम देखेंगे


"लोड इनट्रेस एजेंट" बटन पर क्लिक करें और कंसोल, टेक्स्ट के समान इनट्रेस के कार्यान्वयन पर रिपोर्ट करेगा



कार्यान्वयन चरण सफलतापूर्वक पूरा हो गया है: एक इनट्रेस एजेंट सफलतापूर्वक जावा मशीन में बसा हुआ है, बाइट कोड को बदलने के लिए तैयार है, ट्रेस कमांड के साथ इसकी आपूर्ति करता है, और परिणामों की रिपोर्ट करता है।

हम परिणाम की निगरानी के चरण में आगे बढ़ते हैं, जिसके लिए हम एजेंट प्रबंधन और परिणामों का विश्लेषण (एक अलग आवेदन) लॉन्च करते हैं।

फिर से, दो सरल विकल्प हैं।
1) हमने पहले "सॉफ्टवेयर तरीके" में एजेंट को लागू किया, फिर चलाया
 java -jar intrace-ui.jar 

यहाँ ले जाया गया
github.com/mchr3k/org.intrace/tree/master/binaries/jars/latest_development
2) VisualVM का उपयोग करने के मामले में, "लॉन्च इनट्रेस क्लाइंट" बटन पर क्लिक करें, और, सिद्धांत रूप में, ठीक उसी फ़ाइल को पहले उदाहरण के रूप में लॉन्च किया जाएगा (क्योंकि हमने एक नया इंट्रेस-यूआई.जर पैच किया है)



हम पते में ड्राइव करते हैं, ट्रेस के मापदंडों को कॉन्फ़िगर करते हैं (मैंने एंट्री / एग्जिट + ब्रांच + आर्ग्स को चालू किया), "कक्षाएं ..." बटन दबाएं और वहां स्केजका निर्दिष्ट करें (यह स्केज पैकेज से कक्षाओं में जोड़े जाने के लिए मजबूर करेगा)।
चल रहे "शलजम" के साथ कंसोल में "एंटर" दबाएं (यह मत भूलो कि यह वह है जो जारी रखने के लिए इंतजार कर रहा है) और अंत में हम आउटपुट के रूप में क्लाइंट पर प्रोग्राम निष्पादन श्रृंखला प्राप्त करेंगे:

 [21:52:39.861]:[1]:skazka.Dedka:<init>: {:24 [21:52:39.862]:[1]:skazka.Dedka:<init>: }:24 [21:52:39.862]:[1]:skazka.Dedka:tyanem: {:26 [21:52:39.865]:[1]:skazka.Dedka:tyanem: Arg (target):  [21:52:39.866]:[1]:skazka.Dedka:tyanem: Arg (weight): 200 [21:52:39.868]:[1]:skazka.Babka:<init>: {:30 [21:52:39.869]:[1]:skazka.Babka:<init>: }:30 [21:52:39.871]:[1]:skazka.Babka:tyanem: {:32 [21:52:39.871]:[1]:skazka.Babka:tyanem: Arg (target):  [21:52:39.871]:[1]:skazka.Babka:tyanem: Arg (weight): 185 [21:52:39.878]:[1]:skazka.Vorona:<init>: {:36 [21:52:39.878]:[1]:skazka.Vorona:<init>: }:36 [21:52:39.878]:[1]:skazka.Vorona:tyanem: {:38 [21:52:39.879]:[1]:skazka.Vorona:tyanem: Arg (target):  [21:52:39.879]:[1]:skazka.Vorona:tyanem: Arg (weight): 175 [21:52:39.879]:[1]:skazka.Vorona:tyanem: /:39 [21:52:39.885]:[1]:skazka.Vorona:tyanem: Throw:39: java.lang.RuntimeException:      at skazka.Vorona.tyanem(Repka.java:39) at skazka.Babka.tyanem(Repka.java:32) at skazka.Dedka.tyanem(Repka.java:26) at skazka.Repka.main(Repka.java:11) [21:52:39.885]:[1]:skazka.Vorona:tyanem: }:39 [21:52:39.886]:[1]:skazka.Repka:main: /:13 [21:52:39.890]:[1]:skazka.Repka:processError: {:20 [21:52:39.890]:[1]:skazka.Repka:processError: Arg (ex): java.lang.RuntimeException:      [21:52:39.891]:[1]:skazka.Repka:processError: Return: 1 [21:52:39.891]:[1]:skazka.Repka:processError: }:20 [21:52:39.891]:[1]:skazka.Repka:main: }:16 


प्रत्येक आउटपुट लाइन को निम्न प्रारूप में वर्णित किया गया है
 [ ]:[ ]:::  

जहां:
वर्तमान समय - खुद के लिए बोलता है
स्ट्रीम आइडेंटिफ़ायर - स्ट्रीम की एक विशिष्ट पहचानकर्ता, विभिन्न स्ट्रीम - विभिन्न संख्याएँ (1, 2, 3, 4, ...)
पैकेज - नाम स्थान
विधि - उस विधि का नाम जिसमें निष्पादन होता है
अतिरिक्त जानकारी - स्थिति पर निर्भर करता है

समर्थित ट्रेस प्रकार:
- मेथड इनपुट \ आउटपुट
 [21:52:39.861]:[1]:skazka.Dedka:<init>: {:24 [21:52:39.862]:[1]:skazka.Dedka:<init>: }:24 

या
 [21:52:39.890]:[1]:skazka.Repka:processError: {:20 


- शाखाएँ
 [21:52:39.879]:[1]:skazka.Vorona:tyanem: /:39 

- तर्क (वस्तुओं का प्रदर्शन स्ट्रस्ट्रिंग () के माध्यम से जाता है)
 [21:52:39.865]:[1]:skazka.Dedka:tyanem: Arg (target):  [21:52:39.866]:[1]:skazka.Dedka:tyanem: Arg (weight): 200 

वापसी मान
 [21:38:31.444]:[1]:skazka.Repka:processError: Return: 1 

- अपवाद
 [21:52:39.885]:[1]:skazka.Vorona:tyanem: Throw:39: java.lang.RuntimeException:      at skazka.Vorona.tyanem(Repka.java:39) at skazka.Babka.tyanem(Repka.java:32) at skazka.Dedka.tyanem(Repka.java:26) at skazka.Repka.main(Repka.java:11) 

सामान्य तौर पर, कार्यक्रम की प्रगति को सफलतापूर्वक समझने के लिए सभी की आवश्यकता होती है।

उपरोक्त उदाहरण का उपयोग करके आउटपुट का विश्लेषण करने का अभ्यास करें (जो कुछ तुरंत सहज हो सकता है वह पूरी तरह से स्पष्ट नहीं है, लेकिन यदि आप इसे जल्दी से समझ लेते हैं, तो आपको इसकी आदत पड़ जाती है)।

लेखक के पृष्ठ mchr3k.imtqy.com/org.intrace/howintraceworks.html पर कोड क्या होता है (कैसे निशान की व्यवस्था की जाती है) का एक अच्छा उदाहरण पाया जा सकता है।

मैं आपको बहुत उपयोगी "फ़िल्टर ..." बटन पर तुरंत ध्यान देने की सलाह देता हूं, जो अनावश्यक कचरे से छुटकारा पाने में मदद करता है

एक्लिप्स के साथ मौजूदा एकीकरण आपको जावा एप्लिकेशन को पहले से लागू इनट्रेस एजेंट के साथ चलाने, ट्रेसिंग मापदंडों को कॉन्फ़िगर करने और काम के परिणाम का विश्लेषण करने की अनुमति देता है। अधिक जानकारी के लिए mchr3k.imtqy.com/org.intrace/eclipse.html देखें

कुल

फायदे:
1) मक्खी पर कार्यक्रम की प्रगति पर नज़र रखना:
- विधि कॉल, पारित तर्क, शाखाएं, अपवाद उत्पन्न ...
- बिना पुनर्संयोजन और यहां तक ​​कि एक चल रहे कार्यक्रम को पुनरारंभ किए बिना
2) उपलब्ध कोड (ओपनसोर्स)
3) स्थापित करने और उपयोग करने में आसान
4) क्रॉस-प्लेटफॉर्म समाधान (विंडोज, लिनक्स)
5) लोकप्रिय विकास साधनों के साथ एकीकरण संभव है (ग्रहण, विजुअलवीएम)

नुकसान:
1) मक्खी पर कोड बाइट्स बदलें:
- निष्पादन की गति (प्रदर्शन)
- एजेंट का परिचय मौजूदा प्रक्रिया को "म्यूट" करता है और यह पहले जैसा नहीं होगा (आप एक ही नदी में दो बार प्रवेश नहीं करेंगे)
- कोड बाइट्स के संशोधन "जैसा है" और स्वाभाविक रूप से "अपने जोखिम और जोखिम पर"
2) कोई जन समर्थन नहीं है - केवल एक डेवलपर, लेकिन परियोजना के छोटे आकार और स्रोत कोड की उपलब्धता से मुआवजा दिया जाता है। मुझे खुशी है कि रिपॉजिटरी में आखिरी अपडेट इस पोस्ट के प्रकाशन से कुछ हफ्ते पहले था।
3) उत्पाद को अच्छी तरह से जावा 1.6 पर परीक्षण किया गया है, लेकिन जावा 1.7 पर परीक्षण नहीं किया गया है (और इसके साथ समस्याएं हैं, बग github.com/mchr3k/org.intrace/issues/28 देखें)। जहां तक ​​मैं समझता हूं, लेखक केवल 1.6 का उपयोग करता है, "खुद के लिए" लिखा है और वाणिज्य के लिए बिल्कुल नहीं है, इसलिए जिसे एक नए की आवश्यकता है, उसे लेने और पेंच करने के लिए बहुत आलसी मत बनो

निष्कर्ष में: इनट्रेस एक एजेंट है जो निश्चित रूप से परिचित का हकदार है, और, शायद, आपके लिए एक अपरिहार्य उपकरण बन जाएगा, एक अलग कोण से जावा एप्लिकेशन डिबगिंग का खुलासा करता है, और निश्चित रूप से, किसी को एक से अधिक बार मदद करेगा।

टिप्पणियों और परिवर्धन को ध्यान में रखते हुए, मैं जेएवीए हब में इनट्रेस (साथ ही कई अन्य दिलचस्प एजेंटों की संख्या) को प्राप्त करने की कोशिश करता हूं और मैं मदद के लिए बहुत आभारी रहूंगा।

आपका ध्यान के लिए धन्यवाद और उन लोगों के साथ साझा करना सुनिश्चित करें, जिनकी रुचि हो सकती है!

Source: https://habr.com/ru/post/In219661/


All Articles