Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Java

Java 9 StackWalker: रिफ्लेक्शन फ्रेम्स दिखाना (SHOW_REFLECT_FRAMES)

Java 9 ने java.lang.StackWalker पेश किया - स्टैक ट्रेस तक पहुंच के लिए एक कुशल, आलसी (lazy) API। Option.SHOW_REFLECT_FRAMES विकल्प रिफ्लेक्शन के माध्यम से आह्वान किए गए मेथड्स के स्टैक फ्रेम्स को शामिल करने की अनुमति देता है, जो डिबगिंग के लिए उपयोगी है।

StackWalker अवलोकन

विकल्पविवरण
RETAIN_CLASS_REFERENCEStackFrame.getDeclaringClass() सक्षम करता है
SHOW_REFLECT_FRAMESरिफ्लेक्शन फ्रेम्स दिखाएं (Method.invoke, आदि)
SHOW_HIDDEN_FRAMESछिपे हुए फ्रेम्स दिखाएं (लैम्ब्डा, प्रॉक्सी, आदि)

SHOW_REFLECT_FRAMES उदाहरण

import java.lang.StackWalker;
import java.lang.StackWalker.Option;
import java.lang.StackWalker.StackFrame;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;

public class ReflectionFrameDemo {
    public static void main(String[] args) 
            throws NoSuchMethodException, SecurityException, 
                   IllegalAccessException, IllegalArgumentException, 
                   InvocationTargetException {
        
        // रिफ्लेक्शन के माध्यम से मेथड आह्वान करें
        Method test1Method = Test1.class.getDeclaredMethod("test1");
        test1Method.invoke(null);
    }
}

class Test1 {
    protected static void test1() {
        Test2.test2();
    }
}

class Test2 {
    protected static void test2() {
        // SHOW_REFLECT_FRAMES के साथ स्टैक वॉकर प्राप्त करें
        List stack = StackWalker.getInstance(Option.SHOW_REFLECT_FRAMES)
            .walk(s -> s.collect(Collectors.toList()));
        
        for (StackFrame frame : stack) {
            System.out.printf("%-40s %4d %s%n", 
                frame.getClassName(), 
                frame.getLineNumber(), 
                frame.getMethodName());
        }
    }
}

आउटपुट

Test2                                   22 test2
Test1                                   16 test1
jdk.internal.reflect.NativeMethodAccessorImpl -2 invoke0
jdk.internal.reflect.NativeMethodAccessorImpl 62 invoke
jdk.internal.reflect.DelegatingMethodAccessorImpl 43 invoke
java.lang.reflect.Method                564 invoke
ReflectionFrameDemo                     11 main

विकल्प के बिना तुलना

// SHOW_REFLECT_FRAMES के बिना (डिफ़ॉल्ट)
List stack = StackWalker.getInstance()
    .walk(s -> s.collect(Collectors.toList()));
Test2                                   22 test2
Test1                                   16 test1
ReflectionFrameDemo                     11 main
// रिफ्लेक्शन फ्रेम्स छुपे हुए!

StackFrame API

मेथडवापसी प्रकारविवरण
getClassName()Stringघोषक कक्षा नाम
getMethodName()Stringमेथड नाम
getFileName()Stringस्रोत फ़ाइल नाम
getLineNumber()intलाइन नंबर (-1 यदि अनुपलब्ध)
getDeclaringClass()Class<?>कक्षा ऑब्जेक्ट (RETAIN_CLASS_REFERENCE आवश्यक)
getMethodType()MethodTypeमेथड टाइप (RETAIN_CLASS_REFERENCE आवश्यक)
isNativeMethod()booleanनेटिव मेथड है?
toString()Stringफॉर्मेटेड स्ट्रिंग

उन्नत उपयोग: कस्टम स्ट्रीम प्रोसेसिंग

public class AdvancedStackWalker {
    public static void main(String[] args) {
        // 1. केवल एप्लिकेशन फ्रेम्स (JDK/लाइब्रेरी फ़िल्टर करें)
        StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE)
            .walk(s -> s
                .filter(f -> f.getClassName().startsWith("com.myapp"))
                .forEach(f -> System.out.println(f)));
        
        // 2. पहला गैर-JDK फ्रेम ढूंढें
        StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE)
            .walk(s -> s
                .filter(f -> !f.getClassName().startsWith("java.") 
                          && !f.getClassName().startsWith("jdk."))
                .findFirst()
                .ifPresent(f -> System.out.println("पहला ऐप फ्रेम: " + f)));
        
        // 3. कक्षा रेफरेंस के साथ (रिफ्लेक्शन के लिए)
        StackWalker walker = StackWalker.getInstance(
            Option.RETAIN_CLASS_REFERENCE, Option.SHOW_REFLECT_FRAMES);
        
        walker.walk(s -> s
            .filter(f -> f.getDeclaringClass() != null)
            .forEach(f -> {
                System.out.println("कक्षा: " + f.getDeclaringClass().getName());
                System.out.println("मेथड: " + f.getMethodName());
            }));
    }
}

पारंपरिक API के साथ तुलना

APIलेज़ी?फ़िल्टरिंगकक्षा रेफरेंसरिफ्लेक्शन फ्रेम्स
Thread.getStackTrace()नहीं (ईगर)मैन्युअलनहींनहीं
Throwable.getStackTrace()नहींमैन्युअलनहींनहीं
StackWalkerहांस्ट्रीम APIवैकल्पिकवैकल्पिक

व्यावहारिक उपयोग केस

1. लॉगिंग फ्रेमवर्क एकीकरण

public class LogUtil {
    private static final StackWalker WALKER = StackWalker.getInstance(
        Option.RETAIN_CLASS_REFERENCE);
    
    public static String getCallerClassName() {
        return WALKER.walk(s -> s
            .skip(1) // getCallerClassName को छोड़ें
            .filter(f -> !f.getClassName().startsWith("com.myapp.logging"))
            .map(StackFrame::getClassName)
            .findFirst()
            .orElse("Unknown"));
    }
}

2. प्रदर्शन प्रोफाइलिंग

public class Profiler {
    private static final StackWalker WALKER = StackWalker.getInstance();
    
    public static void profile(Runnable task) {
        long start = System.nanoTime();
        task.run();
        long elapsed = System.nanoTime() - start;
        
        WALKER.walk(s -> s
            .limit(10)
            .forEach(f -> System.out.printf("%s.%s:%d%n", 
                f.getClassName(), f.getMethodName(), f.getLineNumber())));
        
        System.out.println("समय: " + elapsed/1_000_000 + "ms");
    }
}

3. सुरक्षा ऑडिटिंग

public class SecurityAudit {
    public static void checkCallerPermission(String permission) {
        StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE)
            .walk(s -> s
                .skip(1)
                .findFirst()
                .ifPresent(frame -> {
                    Class caller = frame.getDeclaringClass();
                    // कॉलर की अनुमतियां जांचें
                    System.out.println("कॉलर: " + caller.getName() + 
                        " मेथड: " + frame.getMethodName() + 
                        " अनुमति मांग रहा: " + permission);
                }));
    }
}

सर्वोत्तम अभ्यास

  • इंस्टेंस पुनः उपयोग करें: StackWalker.getInstance() कैश्ड इंस्टेंस लौटाता है
  • लेज़ी मूल्यांकन: walk() केवल आवश्यक फ्रेम्स प्रोसेस करता है
  • विकल्प संयोजित करें: getInstance(Option.RETAIN_CLASS_REFERENCE, Option.SHOW_REFLECT_FRAMES)
  • गहरे स्टैक से बचें: limit(), skip(), dropWhile() का उपयोग करें
  • प्रदर्शन: पारंपरिक API से तेज़ जब केवल कुछ फ्रेम्स की आवश्यकता हो

सारांश

  • StackWalker Java 9+ में स्टैक इंस्पेक्शन के लिए आधुनिक API है
  • Option.SHOW_REFLECT_FRAMES रिफ्लेक्शन फ्रेम्स (Method.invoke, आदि) को उजागर करता है
  • स्ट्रीम-आधारित प्रोसेसिंग शक्तिशाली फ़िल्टरिंग/परिवर्तन सक्षम करती है
  • RETAIN_CLASS_REFERENCE कक्षा/मेथड रिफ्लेक्शन के लिए Class ऑब्जेक्ट्स सक्षम करता है
  • Thread.getStackTrace() और Throwable.getStackTrace() से अधिक कुशल
  1. Java में JTextField में पैडिंग कैसे जोड़ें? Java में JTextField में पैडिंग कैसे जोड़ें?

    JTextField JTextComponent क्लास का सबक्लास है और यह सबसे महत्वपूर्ण घटकों में से एक है जो उपयोगकर्ता को सिंगल-लाइन फॉर्मेट में टेक्स्ट मान इनपुट करने की अनुमति देता है। JTextField क्लास ActionListener इंटरफेस जनरेट करेगा जब हम इसके अंदर कुछ इनपुट दर्ज करने का प्रयास करते हैं। JTextField क्लास के महत

  1. - Java में मेंबर इनर क्लास को कैसे इंस्टेंशिएट करें?

    एक क्लास जो एक क्लास के अंदर घोषित की जाती है लेकिन मेथड के बाहर होती है, उसे मेंबर इनर क्लास के रूप में जाना जाता है। हम मेंबर इनर क्लास को दो तरीकों से इंस्टेंशिएट कर सकते हैं: क्लास के भीतर इनवोक किया गया क्लास के बाहर इनवोक किया गया इनर क्लास के नियम आउटर क्लास (वह क्लास जिसमें इनर क्लास ह

  1. - Java में सब-पैकेज का उपयोग कैसे करें

    सबपैकेज सब-डायरेक्टरीज के समान हैं। एक उदाहरण पर विचार करें। कंपनी के पास एक com.apple.computers पैकेज था जिसमें एक Dell.java सोर्स फाइल थी, यह सबडायरेक्टरीज की एक श्रृंखला में समाहित होगी जैसे −....\com\apple\computers\Dell.javaकंपाइलेशन के समय, कंपाइलर इसमें परिभाषित प्रत्येक क्लास, इंटरफेस और एन्