क्यों प्रोजेगार्ड विधि शरीर को खराब नहीं करता है?
क्योंकि यह नहीं कर सकता है।
विधि तर्क और स्थानीय चर के नाम संकलित करते समय बस संग्रहीत नहीं होते हैं।
जो नाम आप देख रहे हैं वे आपके डिकंपेलर द्वारा जेनरेट किए गए हैं।
- संकार्य ढेर पर
- स्थानीय चर
में संकार्य ढेर वास्तव में है:
संकलित कोड के लिए, वहाँ स्थानीय स्तर पर डाटा स्टोर करने के दो तरीके (एक विधि के भीतर यानी) कर रहे हैं बस एक ढेर
स्टैक ऑपरेटरों के लिए जावा वीएम विशिष्टता से Table 7.2 देखें।
आप मूल्यों पॉप कर सकते हैं (pop
), शीर्ष मूल्य (dup
) डुप्लिकेट, शीर्ष दो मान (swap
) और थोड़ा बदल व्यवहार (pop2
, dup_x1
, dup_x2
, dup2
, dup2_x1
, dup2_x2
) के साथ एक ही स्वैप।
और सबसे अधिक, यदि रिटर्न वैल्यू उत्पन्न करने वाले सभी निर्देश स्टैक पर मूल्य को छोड़ देंगे।
इस प्रश्न के लिए महत्वपूर्ण बात यह है कि स्टैक पर चीजें किस प्रकार संदर्भित की जाती हैं, जो किसी अन्य स्टैक के साथ होती है:
शीर्ष स्थिति से संबंधित, और उपयोग किए गए निर्देशों के आधार पर।
कोई असाइन नंबर या नाम नहीं हैं, यह वही है जो वर्तमान में वहां है।
अब, तथाकथित "स्थानीय चर" के लिए: के रूप में अधिक जावा में चर से एक ArrayList
उनमें से
Think।
क्योंकि यह बिल्कुल ठीक है कि आप उन्हें कैसे एक्सेस करते हैं: अनुक्रमणिका द्वारा।
0 से 3 के चर के लिए, विशेष निर्देश हैं (यानी।एकल बाइट) क्योंकि इन्हें अक्सर उपयोग किया जाता है, अन्य सभी चर केवल दो-बाइट निर्देश के माध्यम से पहुंचा जा सकता है, जहां दूसरा बाइट इंडेक्स है।
Table 7.2 फिर से, "लोड" और "स्टोर" देखें।
दोनों तालिकाओं में पहले पांच प्रविष्टियों,, चौड़ा (दो-बाइट) की दुकान/लोड प्रत्येक डेटा प्रकार के लिए निर्देश (ध्यान दें कि, एकल मूल्यों के लिए boolean
, char
, byte
और short
सभी int
में बदल दिए जाते हैं केवल int
छोड़ने float
और Object
सिंगल-स्लॉट मान और long
और double
डबल-स्लॉट वाले के रूप में), अगले बीस निर्देश रजिस्ट्रार 0 से 3 तक सीधे पहुंच के लिए निर्देश हैं, और अंतिम आठ निर्देश सरणी सूचकांक तक पहुंचने के लिए हैं (ध्यान दें कि सरणी के अंदर , boolean
, byte
, char
और short
में परिवर्तित, अंतरिक्ष को बर्बाद न करने के लिए, यही कारण है कि तीन और निर्देश हैं (चार नहीं, byte
और char
के समान आकार हैं))।
दोनों अधिकतम ढेर आकार और स्थानीय चर की संख्या सीमित कर रहे हैं, और के रूप में Section 4.7.3 (max_stack
और max_locals
) में परिभाषित, प्रत्येक विधि के Code
विशेषता के शीर्षक में दिया जाना चाहिए।
स्थानीय चर के बारे में दिलचस्प बात यह है कि वे विधि तर्क के रूप में दोगुनी हैं, जिसका अर्थ है कि स्थानीय चर की संख्या विधि तर्कों की संख्या से कम कभी नहीं हो सकती है।
ध्यान दें कि जावा वीएम के मानों की गणना करते समय, long
और double
के चर के दो मानों के रूप में माना जाता है, और तदनुसार दो "स्लॉट" की आवश्यकता होती है।
यह भी ध्यान दें कि गैर स्थैतिक तरीकों के लिए, तर्क 0 this
होगा, जिसके लिए स्वयं के लिए एक और "स्लॉट" की आवश्यकता होगी।
कहा जा रहा है, चलिए कुछ कोड देखें!
उदाहरण:
class Test
{
public static void main(String[] myArgs) throws NumberFormatException
{
String myString = "42";
int myInt = Integer.parseInt(myString);
double myDouble = (double)myInt * 42.0d;
System.out.println(myDouble);
}
}
यहाँ हम तीन स्थानीय चर myString
, myInt
और myDouble
, प्लस एक तर्क myArgs
है। - वर्ग
java.lang.NumberFormatException
- वर्ग
java.lang.String
- वर्ग
java.lang.Integer.parseInt
- विधि
java.lang.String[]
:
इसके अलावा, हम दो स्थिरांक "42"
और 42.0d
, और बाहरी संदर्भ का एक बहुत है java.lang.System.out
- फ़ील्ड
- ,210 - विधि
और कुछ निर्यात: Test
और main
, प्लस डिफ़ॉल्ट निर्माता कि संकलक हमारे लिए उत्पन्न होगा।
सभी स्थिरांक, संदर्भ और निर्यात Constant Pool पर निर्यात किए जाएंगे - स्थानीय चर और तर्क नाम नहीं होंगे।
संकलन और वर्ग (javap -c Test
का प्रयोग करके) वियोजन पैदावार:
Compiled from "Test.java"
class Test {
Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]) throws java.lang.NumberFormatException;
Code:
0: ldc #2 // String 42
2: astore_1
3: aload_1
4: invokestatic #3 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
7: istore_2
8: iload_2
9: i2d
10: ldc2_w #4 // double 42.0d
13: dmul
14: dstore_3
15: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
18: dload_3
19: invokevirtual #7 // Method java/io/PrintStream.println:(D)V
22: return
}
डिफ़ॉल्ट निर्माता इसके अलावा, हम अपने main
विधि, चरण दर चरण देख सकते हैं।
नोट कैसे myString
dstore_3
और dload_3
साथ istore_2
और iload_2
, और myDouble
साथ astore_1
और aload_1
, myInt
के साथ पहुँचा है।
myArgs
कहीं भी नहीं पहुंचाया गया है, इसलिए इसके साथ कोई बाइटकोड नहीं है, लेकिन विधि की शुरुआत में, स्ट्रिंग सरणी का संदर्भ स्थानीय चर 1 में होगा, जो "42"
के संदर्भ में जल्द ही अधिलेखित हो जाता है।
javap
भी अगर आप इसे -v
ध्वज पारित आप लगातार पूल दिखाई देगा, लेकिन यह वास्तव में के बाद से लगातार पूल से सभी प्रासंगिक जानकारी वैसे भी टिप्पणी में प्रदर्शित किया जाता है, उत्पादन के लिए सार्थक नहीं है।
लेकिन अब, देखते हैं कि डीकंपलर क्या उत्पादन करते हैं!
जद-जीयूआई 0.3.5 (जद-कोर 0.6.2):
import java.io.PrintStream;
class Test
{
public static void main(String[] paramArrayOfString)
throws NumberFormatException
{
String str = "42";
int i = Integer.parseInt(str);
double d = i * 42.0D;
System.out.println(d);
}
}
प्रोसिओन 0.5.28:
class Test
{
public static void main(final String[] array) throws NumberFormatException {
System.out.println(Integer.parseInt("42") * 42.0);
}
}
नोट कैसे सब कुछ है कि लगातार पूल करने के लिए निर्यात किया गया था बनी रहती है, जबकि जेडी-जीयूआई स्थानीय चर के लिए कुछ नाम चुनता है, और प्रोसीन पूरी तरह से उन्हें अनुकूलित करता है।
तर्क का नाम - paramArrayOfString
बनाम array
(मूल myArgs
बनाम) - यह एक आदर्श उदाहरण है, हालांकि, यह दिखाने के लिए कि अब कोई "सही" नाम नहीं है, और decompilers को बस चुनने के कुछ पैटर्न पर निर्भर होना है नाम।
मुझे नहीं पता कि आपके अपूर्ण कोड में "सत्य" नाम कहां से आ रहे हैं, लेकिन मुझे काफी यकीन है कि वे जार फ़ाइल में निहित नहीं हैं।
शायद आपके आईडीई की सुविधा?
क्या "obfuscated" कोड असली जावा कोड या जावा कोड है जिसे डिकंपिल्ड किया गया है? मेरी समझ यह है कि एक बाइटकोड फ़ाइल बस विधि पैरामीटर और स्थानीय चर के नाम रिकॉर्ड नहीं करता है। (यदि यह ProGuard द्वारा उत्सर्जित स्रोत कोड है, तो इसे संकलित करने का प्रयास करें। फिर .class फ़ाइल को डीकंपाइल करें ... या javap का उपयोग करके इसे देखें।) –
@StephenC यह डीकंपिल्ड जावा कोड है। मैंने .jar फ़ाइल को obfuscated (proguard के साथ, .jar संकलित करने के बाद), फिर पहले obfuscated .jar decompiled। .jar फ़ाइलें (बाइटकोड) मूल स्रोत कोड से लगभग सभी डेटा स्टोर करती है (टिप्पणियों और वाक्यविन्यास स्वरूपण को छोड़कर)। – Victor2748