2010-05-15 10 views
8

पर विचार करें इस IMHO (सरल) उदाहरण:क्या कोई जावा डिकंपेलर है जो ओवरलोडेड विधियों को कॉल को सही ढंग से डिमंपाइल कर सकता है?

public class DecompilerTest { 
    public static void main(String[] args) { 
     Object s1 = "The", s2 = "answer"; 
     doPrint((Object) "You should know:"); 
     for (int i = 0; i < 2; i++) { 
      doPrint(s1); 
      doPrint(s2); 
      s1 = "is"; 
      s2 = new Integer(42); 
     } 
     System.out.println(); 
    } 

    private static void doPrint(String s1) { 
     System.out.print("Wrong!"); 
    } 

    private static void doPrint(Object s1) { 
     System.out.print(s1 + " "); 
    } 
} 

स्रोत/लक्ष्य 1.1 स्तर डिबग जानकारी के बिना के साथ संकलित (अर्थात् कोई स्थानीय चर जानकारी मौजूद होना चाहिए) और यह डिकंपाइल की कोशिश करो। मैंने जाड, जेडी-जीयूआई और फर्नाफ्लॉवर की कोशिश की, और उनमें से सभी को कम से कम एक बार गलत कहा गया (यानी कार्यक्रम कम से कम एक बार "गलत!" मुद्रित किया गया है)

क्या वास्तव में कोई जावा डिकंपेलर नहीं है जो सही अनुमान लगा सकता है ऐसा लगता है कि यह गलत अधिभार को कॉल नहीं करेगा?

संपादित करें: लक्ष्य स्तर 1.1 ताकि जावा 6-विशिष्ट फास्ट-सत्यापन जानकारी मौजूद न हो। इससे डिकंपेलर को एक सुराग मिल सकता है जिसे एस 1 को Object के रूप में घोषित किया गया है और String के रूप में नहीं। Decompilers इस जानकारी के बिना भी कोड को संकुचित करने में सक्षम होना चाहिए (आवश्यक रूप से मूल परिवर्तनीय प्रकार नहीं मिलता है, लेकिन एक ही व्यवहार दिखाएं), खासकर जब से बहुत सारे obfuscators इसे भी पट्टी करते हैं।

क्या डीकम्पाइलर गलत:

  • वे पहली बार कॉल में (Object) लिए डाली याद किया।
  • उन्होंने s1 के प्रकार String के रूप में अनुमानित किया, लेकिन doPrint पर कॉल में एक कलाकार जोड़ने के लिए भूल गए (ताकि ऑब्जेक्ट संस्करण के बजाय स्ट्रिंग संस्करण को कॉल किया जा सके)।
  • एक क्रैपी एक (मैंने सूचीबद्ध भी नहीं किया है) स्ट्रिंग होने के लिए s2 के प्रकार का भी अनुमान लगाता है, जिससे असंगत कोड होता है।

किसी भी मामले में, यह कोड कभी भी String अधिभार को कॉल नहीं करता है, लेकिन अपूर्ण कोड किया गया है।

+0

आपका क्या मतलब है "उन्हें कॉल गलत मिला"? अपघटन के बाद वे क्या स्रोत उत्पन्न करते हैं? – skaffman

+1

एचएम, और क्यों 1.1? – Bozho

उत्तर

4

Krakatau सही ढंग से सभी अतिभारित तरीकों, यहां तक ​​कि तरीकों आदिम प्रकार है, जो सबसे डीकम्पाइलर गलत पर अतिभारित संभालती है। यह हमेशा सही प्रकार के बुलाए गए विधि के लिए तर्क डालता है, इसलिए कोड आवश्यक से अधिक अव्यवस्थित हो सकता है, लेकिन कम से कम यह सही है।

प्रकटीकरण: मैं क्राकाटो के लेखक हूं।

3

डीकंपलिंग के लिए जेडक्लिप्स ग्रहण प्लगइन भी जॉडे डीकंपलर प्रदान करता है, जिसे आप आजमा सकते हैं। जैड हारने पर मैं इसका इस्तेमाल करता हूं।

इसके अलावा डेवा डीकंपलर सूट का उपयोग करता है - पिछली बार मैंने देखा - मूल जावा कोड के पुनर्निर्माण में बहुत महत्वाकांक्षी था। मैंने आपके उदाहरण के साथ प्रयास नहीं किया है, लेकिन आप एक नज़र रखना चाहते हैं। http://www.sable.mcgill.ca/dava/

+0

दावा दूसरों की तरह विफल रहा। जोड ने काम किया, लेकिन चूंकि जोड किसी भी obfuscator के माध्यम से चलने वाले लगभग हर कार्यक्रम पर दुर्घटनाग्रस्त हो जाता है, यह वास्तव में मेरी मदद नहीं करता है :(मान लीजिए मैंने गलत सवाल पूछा है।) – mihi

+3

डाउनवोट _and_ उत्तर स्वीकार करते हैं? वह नया था :) –

+0

ने मेरा स्वीकार्य उत्तर बदल दिया है यदि आप डाउनवॉटेड और स्वीकार नहीं करना चाहते हैं :) (मैंने पहले आपको नीचे गिरा दिया क्योंकि आपके सुझावों ने काम नहीं किया था, लेकिन फिर फैसला किया कि सभी डाउनवॉटेड उत्तरों से आप सबसे अच्छे थे) - बीटीडब्ल्यू आप कहां देख सकते हैं कि यह मैं था जो दोनों नीचे आ गए और स्वीकार किए गए? – mihi

9

Hallo mihi,

देर प्रतिक्रिया के लिए खेद है। मैं http://www.reversed-java.com/fernflower/forum?threadfolder=2_DE

से मेरा उत्तर कॉपी कर रहा हूं आपकी समस्या वास्तव में एक प्रसिद्ध व्यक्ति है। चलो देखते हैं:

1) शुद्ध बाइटकोड में ऑब्जेक्ट चर के प्रकार के बारे में कोई जानकारी नहीं है, इसलिए पहले पास एस 1 और एस 2 को ऑब्जेक्ट के रूप में घोषित किया गया है।

2) डीकंपलर प्रत्येक वैरिएबल (= "फर्नाफ्लॉवर में कार्यान्वित सबसे सरल प्रकार सिद्धांत" को सर्वोत्तम संभव प्रकार असाइन करने के लिए कड़ी मेहनत कर रहा है। इसलिए एस 1 और एस 2 को स्ट्रिंग के उदाहरणों के रूप में सही ढंग से पहचाना जाता है।

3) doPrint की प्रार्थना किए जाने पर हमें
निजी स्थिर शून्य doPrint (वस्तु एस 1)

4) सब कुछ ठीक अब तक सही विधि के लिए एक सीधा लिंक दे, है ना?अब हमारे पास एक स्ट्रिंग वेरिएबल एस 1 एक फ़ंक्शन पर पास हो गया है, जो ऑब्जेक्ट की अपेक्षा करता है। क्या हमें इसे डालने की ज़रूरत है? ऐसा नहीं है, आप सोचेंगे, क्योंकि ऑब्जेक्ट एक सुपर-स्ट्रिंग स्ट्रिंग है। और फिर भी हम करते हैं - क्योंकि एक ही वर्ग के साथ एक ही नाम और एक अलग पैरामीटर हस्ताक्षर के साथ एक और कार्य है। तो हमें पता लगाने के लिए कि क्या एक कलाकार की जरूरत है या नहीं, पूरी कक्षा का विश्लेषण करने की आवश्यकता है।

5) आम तौर पर, इसका मतलब है कि हमें जावा रनटाइम समेत सभी पुस्तकालयों में सभी संदर्भित कक्षाओं का विश्लेषण करने की आवश्यकता है। काम का एक बड़ा भार! दरअसल, यह सुविधा फर्नाफ्लॉवर के कुछ अल्फा संस्करण में लागू की गई थी, लेकिन इसे अभी तक प्रदर्शन और मेमोरी जुर्माना के कारण उत्पादन में नहीं बनाया गया है। अन्य उल्लिखित decompilers डिजाइन द्वारा इस क्षमता की कमी है।

आशा मैं स्पष्ट किया है चीज़ें थोड़ी :)

+0

हां, मुझे सामान्य समस्या पता है (यही कारण है कि मेरे ऊपर उपरोक्त नमूने में एक लंबी कक्षा को कम करना मुश्किल नहीं था)। लेकिन, जैसा कि मैं इसे समझता हूं, यदि आपके पास लक्ष्य वर्ग के बारे में कक्षा की जानकारी नहीं है, तो आप हमेशा पैरामीटर के सटीक प्रकार में एक (अनावश्यक) कास्ट जोड़ सकते हैं, है ना? बाद में आप सभी अनिवार्य कास्ट को हटाने के लिए ग्रहण के त्वरितफिक्स का उपयोग कर सकते हैं। (i। ई।कोड को डिकंपलिंग करते समय मैं सौंदर्य के लिए शुद्धता पसंद करूंगा) – mihi

+0

आप सही हैं, यह किया जा सकता है। केवल नकारात्मक पक्ष यह होगा कि हम इन सभी अनावश्यक जानवरों के साथ कुछ बहुत बदसूरत कोड उत्पन्न करते हैं। मैं इस व्यवहार के लिए एक विकल्प लागू करूंगा, सुझाव के लिए धन्यवाद। – Stiver

+0

"शुद्ध बाइटकोड में ऑब्जेक्ट वैरिएबल के प्रकार के बारे में कोई जानकारी नहीं है" –

3

Procyon ओवरलोडेड विधि आमंत्रणों को सही ढंग से संभालना चाहिए। क्राकाटो की तरह, प्रोसीन प्रारंभ में प्रत्येक विधि तर्क के लिए दावा करता है जो लक्ष्य विधि से बिल्कुल मेल नहीं खाता है। हालांकि, इनमें से अधिकतर विघटन के बाद के चरण के दौरान हटा दिए जाएंगे जो अनावश्यक जानवरों की पहचान और उन्मूलन करते हैं। Procyon केवल कॉल तर्कों पर रोक देगा यदि यह सत्यापित कर सकता है कि ऐसा करने से कॉल को किसी भिन्न विधि से बाध्यकारी न हो। उदाहरण के लिए, यदि .class विधि को घोषित नहीं किया जा सकता है, तो यह कास्ट को हटाने का प्रयास नहीं करेगा, क्योंकि इसका कोई तरीका नहीं है कि अधिभार क्या संघर्ष कर सकता है।

2

पिछले जवाब को जोड़ना:

  • सीएफआर
  • जद
  • Fernflower
  • के सभी

    • प्रोसिओन: यहाँ एक मार्च 2015 के रूप में आधुनिक डीकम्पाइलर की सूची है वे अधिभारित तरीकों का समर्थन करते हैं।

      आप उपरोक्त डीकंपलर का उल्लेख ऊपर परीक्षण कर सकते हैं, कोई इंस्टॉलेशन आवश्यक नहीं है और अपनी खुद की शिक्षित पसंद कर सकते हैं। क्लाउड में जावा डिकंपेलर: http://www.javadecompilers.com/

    +0

    सुनिश्चित नहीं है कि जेडी और जेडीकोर समान हैं, लेकिन रिकॉर्ड के लिए: उस वेबसाइट से जेडीकोर इस प्रश्न से नमूना को कम करने में विफल रहता है – mihi

    +0

    जेडी और जेडीकोर समान हैं। यह बुरा है यह असफल रहा। उम्मीद है कि अन्य decompilers आगे बढ़े? –