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

Java 9 StackWalker: स्टैक फ्रेम्स छोड़ना (skip/dropWhile)

Java 9 का StackWalker स्टैक फ्रेम्स पर शक्तिशाली स्ट्रीम-आधारित फ़िल्टरिंग प्रदान करता है, जिसमें skip(n) और dropWhile(predicate) शामिल हैं जो अप्रासंगिक फ्रेम्स (जैसे लॉगिंग/फ्रेमवर्क कोड) को बायपास करते हैं।

स्ट्रीम ऑपरेशंस के साथ फ़िल्टरिंग

import java.lang.StackWalker;
import java.lang.StackWalker.StackFrame;
import java.util.List;
import java.util.stream.Collectors;

public class StackWalkerSkipDemo {
    public static void main(String[] args) {
        new StackWalkerSkipDemo().stackWalk();
    }
    
    private void stackWalk() {
        new StackWalker1().stackWalk1();
    }
    
    private class StackWalker1 {
        public void stackWalk1() { new StackWalker2().stackWalk2(); }
    }
    
    private class StackWalker2 {
        public void stackWalk2() { new StackWalker3().stackWalk3(); }
    }
    
    private class StackWalker3 {
        public void stackWalk3() { new StackWalker4().stackWalk4(); }
    }
    
    private class StackWalker4 {
        public void stackWalk4() {
            // RETAIN_CLASS_REFERENCE के साथ वॉकर प्राप्त करें
            List framesAfterSkip = StackWalker.getInstance(
                StackWalker.Option.RETAIN_CLASS_REFERENCE)
                .walk(s -> s.skip(2).collect(Collectors.toList()));
            
            System.out.println("2 फ्रेम्स छोड़ने के बाद:");
            framesAfterSkip.forEach(System.out::println);
        }
    }
}

आउटपुट

2 फ्रेम्स छोड़ने के बाद:
StackWalkerSkipDemo$StackWalker2.stackWalk2(StackWalkerSkipDemo.java:29)
StackWalkerSkipDemo$StackWalker1.stackWalk1(StackWalkerSkipDemo.java:24)
StackWalkerSkipDemo.stackWalk(StackWalkerSkipDemo.java:19)
StackWalkerSkipDemo.main(StackWalkerSkipDemo.java:9)

skip() बनाम dropWhile() बनाम filter()

ऑपरेशनव्यवहारउपयोग केस
skip(n)पहले n फ्रेम्स छोड़ेंज्ञात फ्रेमवर्क/लॉगिंग लेयर्स
dropWhile(pred)शर्त सत्य रहने तक छोड़ेंडायनामिक फ़िल्टरिंग (पैकेज प्रीफिक्स तक)
filter(pred)शर्त से मेल खाने वाले रखेंसमावेशी फ़िल्टरिंग
limit(n)अधिकतम n फ्रेम्स लेंट्रंकेट गहरे स्टैक

व्यावहारिक पैटर्न

1. ज्ञात फ्रेमवर्क फ्रेम्स छोड़ें

// पहले 3 फ्रेम्स छोड़ें (लॉगिंग, AOP, फ्रेमवर्क)
StackWalker.getInstance().walk(s -> s.skip(3).forEach(System.out::println));

2. पैकेज प्रीफिक्स द्वारा ड्रॉप करें


// JDK/लाइब्रेरी फ्रेम्स छोड़ें, पहले ऐप फ्रेम से शुरू करें
StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE)
    .walk(s -> s
        .dropWhile(f -> f.getClassName().startsWith("java.") 
                     || f.getClassName().startsWith("jdk.")
                     || f.getClassName().startsWith("org.springframework.")
                     || f.getClassName().startsWith("org.apache.logging."))
        .forEach(f -> System.out.println(f.getClassName() + "." + f.getMethodName())));

3. पहला ऐप्लिकेशन फ्रेम ढूंढें

public static StackFrame findCaller(Class loggerClass) {
    return StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE)
        .walk(s -> s
            .dropWhile(f -> f.getDeclaringClass() == loggerClass 
                         || f.getClassName().startsWith("java.util.logging"))
            .findFirst()
            .orElse(null));
}

4. लॉगिंग के लिए कस्टम फ़िल्टर

public class LogStackWalker {
    private static final StackWalker WALKER = StackWalker.getInstance(
        Option.RETAIN_CLASS_REFERENCE);
    
    private static final Set EXCLUDED_PREFIXES = Set.of(
        "java.", "jdk.", "sun.", "org.apache.logging.", 
        "org.slf4j.", "ch.qos.logback.", "com.myapp.logging");
    
    public static StackFrame getCallerFrame() {
        return WALKER.walk(s -> s
            .dropWhile(f -> EXCLUDED_PREFIXES.stream()
                .anyMatch(prefix -> f.getClassName().startsWith(prefix)))
            .findFirst()
            .orElse(null));
    }
    
    public static String getCallerInfo() {
        StackFrame frame = getCallerFrame();
        if (frame == null) return "Unknown";
        return String.format("%s.%s:%d", 
            frame.getClassName(), frame.getMethodName(), frame.getLineNumber());
    }
}

पूर्ण उदाहरण: कई फ़िल्टर

import java.lang.StackWalker.*;
import java.util.*;

public class ComprehensiveStackFilter {
    public static void main(String[] args) {
        demoSkip();
        demoDropWhile();
        demoFilter();
        demoCombined();
    }
    
    static void demoSkip() {
        System.out.println("=== skip(2) ===");
        walkAndPrint(s -> s.skip(2));
    }
    
    static void demoDropWhile() {
        System.out.println("\n=== dropWhile (java/jdk छोड़ें) ===");
        walkAndPrint(s -> s.dropWhile(f -> 
            f.getClassName().startsWith("java.") || 
            f.getClassName().startsWith("jdk.")));
    }
    
    static void demoFilter() {
        System.out.println("\n=== filter (केवल com.example) ===");
        walkAndPrint(s -> s.filter(f -> 
            f.getClassName().startsWith("com.example.")));
    }
    
    static void demoCombined() {
        System.out.println("\n=== संयुक्त: dropWhile + limit(5) ===");
        walkAndPrint(s -> s
            .dropWhile(f -> f.getClassName().startsWith("java.") 
                         || f.getClassName().startsWith("jdk."))
            .limit(5));
    }
    
    static void walkAndPrint(java.util.function.Function<
            Stream, Stream> processor) {
        StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE)
            .walk(s -> processor.apply(s).collect(Collectors.toList()))
            .forEach(f -> System.out.printf("  %s.%s:%d%n", 
                f.getClassName(), f.getMethodName(), f.getLineNumber()));
    }
    
    // कॉल स्टैक उत्पन्न करने के लिए नेस्टेड कॉल्स
    static { a(); }
    static void a() { b(); }
    static void b() { c(); }
    static void c() { d(); }
    static void d() { e(); }
    static void e() { f(); }
    static void f() { g(); }
    static void g() { /* स्टैक यहाँ कैप्चर किया गया */ }
}

प्रदर्शन लाभ

  • लेज़ी मूल्यांकन: स्टैक फ्रेम्स केवल मांग पर कैप्चर किए जाते हैं
  • skip(100) केवल 100 फ्रेम्स चलता है, पूरे स्टैक को नहीं
  • Thread.getStackTrace() हमेशा पूर्ण सरणी आवंटित करता है
  • limit(10) के साथ StackWalker केवल 10 फ्रेम्स कैप्चर करता है

सामान्य पैटर्न

// पैटर्न 1: लॉगिंग फ्रेमवर्क के लिए कॉलर ढूंढें
StackFrame caller = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE)
    .walk(s -> s
        .dropWhile(f -> isLoggingFramework(f.getClassName()))
        .findFirst()
        .orElse(null));

// पैटर्न 2: शीर्ष N ऐप्लिकेशन फ्रेम्स प्राप्त करें
List topFrames = StackWalker.getInstance()
    .walk(s -> s
        .dropWhile(f -> isSystemFrame(f.getClassName()))
        .limit(10)
        .collect(Collectors.toList()));

// पैटर्न 3: रिफ्लेक्शन फ्रेम्स के साथ (डिबगिंग)
List withReflection = StackWalker.getInstance(
    Option.SHOW_REFLECT_FRAMES, Option.RETAIN_CLASS_REFERENCE)
    .walk(s -> s.collect(Collectors.toList()));

सारांश

  • skip(n) - निश्चित संख्या में फ्रेम्स छोड़ें
  • dropWhile(pred) - शर्त सत्य रहने तक छोड़ें (डायनामिक)
  • filter(pred) - मेल खाने वाले फ्रेम्स रखें
  • limit(n) - परिणामों को काटें
  • पारंपरिक Thread.getStackTrace() की तुलना में अधिक कुशल
  • जटिल फ़िल्टरिंग के लिए स्ट्रीम ऑपरेशंस संयोजित करें
  1. - Java में Packages (पैकेजेस)

    Java में पैकेजेस का उपयोग नामकरण संघर्षों को रोकने, एक्सेस नियंत्रित करने, क्लासेज, इंटरफेस, एन्यूमरेशन और एनोटेशन की खोज/पता लगाने और उपयोग को आसान बनाने के लिए किया जाता है।एक पैकेज को संबंधित टाइप्स (क्लासेज, इंटरफेस, एन्यूमरेशन और एनोटेशन) के समूह के रूप में परिभाषित किया जा सकता है जो एक्सेस सु

  1. - Java में दूसरे पैकेज में क्लासेज का उपयोग कैसे करें

    आप इसे एक उदाहरण का उपयोग करके समझ सकते हैं जहां एक Boss क्लास payroll पैकेज में परिभाषित है।package payroll; public class Boss { public void payEmployee(Employee e) { e.mailCheck(); } }यदि Employee क्लास payroll पैकेज में नहीं है? Boss क्लास को तब किसी अन्य पैकेज में क्लास को स

  1. - Java में JSON पार्स करना: लोकप्रिय लाइब्रेरी के साथ व्यापक गाइड

    इस ट्यूटोरियल में हम देखेंगे कि विभिन्न लाइब्रेरी का उपयोग करके Java में JSON कैसे पार्स करें। JSON का मतलब JavaScript Object Notation है, और यह JavaScript के सबसेट पर आधारित है। डेटा-एक्सचेंज फॉर्मेट के रूप में, यह वेब प्रोग्रामिंग में व्यापक रूप से उपयोग किया जाता है। यहां हम दिखाते हैं कि org.jso