क्या जावा में कोड का एक स्निपेट बनाना संभव है जो काल्पनिक java.lang.ChuckNorrisException
अस्थिर बना देगा ?
मन में आए विचार उदाहरण इंटरसेप्टर या पहलू-उन्मुख प्रोग्रामिंग के लिए उपयोग कर रहे हैं ।
finalize()
?
क्या जावा में कोड का एक स्निपेट बनाना संभव है जो काल्पनिक java.lang.ChuckNorrisException
अस्थिर बना देगा ?
मन में आए विचार उदाहरण इंटरसेप्टर या पहलू-उन्मुख प्रोग्रामिंग के लिए उपयोग कर रहे हैं ।
finalize()
?
जवाबों:
मैंने यह कोशिश नहीं की है, इसलिए मुझे नहीं पता कि जेवीएम इस तरह से कुछ प्रतिबंधित करेगा, लेकिन शायद आप कोड को संकलित कर सकते हैं जो फेंकता है ChuckNorrisException
, लेकिन रनटाइम में एक वर्ग परिभाषा प्रदान करता हैChuckNorrisException
जिसमें थ्रोएबल का विस्तार नहीं होता है ।
अपडेट करें:
यह काम नहीं करता है। यह एक सत्यापन त्रुटि उत्पन्न करता है:
Exception in thread "main" java.lang.VerifyError: (class: TestThrow, method: ma\
in signature: ([Ljava/lang/String;)V) Can only throw Throwable objects
Could not find the main class: TestThrow. Program will exit.
अद्यतन 2:
वास्तव में, आप यह काम कर सकते हैं यदि आप बाइट कोड सत्यापनकर्ता को अक्षम करते हैं! ( -Xverify:none
)
अद्यतन 3:
घर से निम्नलिखित लोगों के लिए, यहाँ पूरी स्क्रिप्ट है:
निम्नलिखित कक्षाएं बनाएं:
public class ChuckNorrisException
extends RuntimeException // <- Comment out this line on second compilation
{
public ChuckNorrisException() { }
}
public class TestVillain {
public static void main(String[] args) {
try {
throw new ChuckNorrisException();
}
catch(Throwable t) {
System.out.println("Gotcha!");
}
finally {
System.out.println("The end.");
}
}
}
संकलन कक्षाएं:
javac -cp . TestVillain.java ChuckNorrisException.java
Daud:
java -cp . TestVillain
Gotcha!
The end.
बाहर टिप्पणी "RuntimeException फैली" और केवल recompileChuckNorrisException.java
:
javac -cp . ChuckNorrisException.java
Daud:
java -cp . TestVillain
Exception in thread "main" java.lang.VerifyError: (class: TestVillain, method: main signature: ([Ljava/lang/String;)V) Can only throw Throwable objects
Could not find the main class: TestVillain. Program will exit.
सत्यापन के बिना चलाएं:
java -Xverify:none -cp . TestVillain
The end.
Exception in thread "main"
Object
बजाय पकड़, तो क्या Throwable
? (संकलक इसे अनुमति नहीं देगा, लेकिन चूंकि हमने पहले ही सत्यापनकर्ता को अक्षम कर दिया है, हो सकता है कि कोई इसे करने के लिए
यह विचार करने के बाद, मैंने सफलतापूर्वक एक अप्राप्य अपवाद बनाया है। मैंने इसका नाम चुना JulesWinnfield
, हालांकि, चक के बजाय, क्योंकि यह एक मशरूम-क्लाउड-बिछाने-मां-अपवाद है। इसके अलावा, यह वास्तव में आपके दिमाग में नहीं था, लेकिन यह निश्चित रूप से पकड़ा नहीं जा सकता है। का निरीक्षण करें:
public static class JulesWinnfield extends Exception
{
JulesWinnfield()
{
System.err.println("Say 'What' again! I dare you! I double dare you!");
System.exit(25-17); // And you shall know I am the LORD
}
}
public static void main(String[] args)
{
try
{
throw new JulesWinnfield();
}
catch(JulesWinnfield jw)
{
System.out.println("There's a word for that Jules - a bum");
}
}
ए टी वॉयला! पकड़ा ना गया अपवाद।
आउटपुट:
Daud:
वही से दुबारा कहें! मैं तुम्हें चुनौती देता हूं! मुझमे तुमसे दुगुनी हिम्मत है!
जावा परिणाम: 8
निर्माण सफलता (कुल समय: 0 सेकंड)
जब मेरे पास थोड़ा और समय होगा, मैं देखूंगा कि क्या मैं किसी और चीज के साथ नहीं आ सकता।
इसके अलावा, इसे देखें:
public static class JulesWinnfield extends Exception
{
JulesWinnfield() throws JulesWinnfield, VincentVega
{
throw new VincentVega();
}
}
public static class VincentVega extends Exception
{
VincentVega() throws JulesWinnfield, VincentVega
{
throw new JulesWinnfield();
}
}
public static void main(String[] args) throws VincentVega
{
try
{
throw new JulesWinnfield();
}
catch(JulesWinnfield jw)
{
}
catch(VincentVega vv)
{
}
}
एक स्टैक ओवरफ्लो का कारण बनता है - फिर से, अपवाद अनकहा रहता है।
JulesWinfield
? क्या सिस्टम को फेंकने से पहले एक डरावना पड़ाव पर नहीं आएगा?
throw new Whatever()
वास्तव में दो भाग हैं: Whatever it = new Whatever(); throw it;
और दूसरे भाग तक पहुँचने से पहले सिस्टम मर जाता है।
class cn extends exception{private cn(){}}
इस तरह के एक अपवाद के साथ यह स्पष्ट रूप System.exit(Integer.MIN_VALUE);
से कंस्ट्रक्टर से उपयोग करने के लिए अनिवार्य होगा क्योंकि यह ऐसा होगा यदि आप इस तरह के अपवाद को फेंक देते हैं;)
while(true){}
के बजाय System.exit()
।
System.exit()
जो इसे अस्वीकार करता है। यह कंस्ट्रक्टर को एक अलग अपवाद (SecurityException) में बदल देगा, जिसे पकड़ा जा सकता है।
कोई भी कोड Throwable को पकड़ सकता है। तो नहीं, आप जो भी अपवाद बनाते हैं वह थ्रोबेबल का उपवर्ग होने वाला है और पकड़े जाने के अधीन होगा।
hang
: P
public class ChuckNorrisException extends Exception {
public ChuckNorrisException() {
System.exit(1);
}
}
(दी गई, तकनीकी रूप से यह अपवाद वास्तव में कभी नहीं फेंका गया है, लेकिन एक उचित ChuckNorrisException
नहीं फेंका जा सकता है - यह आपको पहले फेंक देता है)
आपके द्वारा फेंके गए किसी भी अपवाद को थ्रोबेबल का विस्तार करना होगा, इसलिए इसे हमेशा पकड़ा जा सकता है। तो जवाब है नहीं।
आप यह मुश्किल को संभालने के लिए बनाना चाहते हैं, तो आप ओवरराइड कर सकते हैं तरीकों getCause(), getMessage()
, getStackTrace()
, toString()
एक और फेंकने के लिए java.lang.ChuckNorrisException
।
catch(Throwable t)
यह केवल चर में संग्रहीत करता है इसलिए मेरे सुझाव केवल अगले ब्लॉक में लागू होते हैं जब उपयोगकर्ता अपवाद के साथ सामना करना चाहता है
मेरा उत्तर @ jtahlborn के विचार पर आधारित है, लेकिन यह पूरी तरह से काम करने वाला जावा प्रोग्राम है, जिसे एक JAR फ़ाइल में पैक किया जा सकता है और यहां तक कि वेब एप्लिकेशन के एक हिस्से के रूप में आपके पसंदीदा एप्लिकेशन सर्वर पर भी तैनात किया जा सकता है ।
सबसे पहले, चलो ChuckNorrisException
वर्ग को परिभाषित करते हैं ताकि यह शुरुआत से जेवीएम को दुर्घटनाग्रस्त न करे (चक वास्तव में जेवीएम को दुर्घटनाग्रस्त करना पसंद करता है :)
package chuck;
import java.io.PrintStream;
import java.io.PrintWriter;
public class ChuckNorrisException extends Exception {
public ChuckNorrisException() {
}
@Override
public Throwable getCause() {
return null;
}
@Override
public String getMessage() {
return toString();
}
@Override
public void printStackTrace(PrintWriter s) {
super.printStackTrace(s);
}
@Override
public void printStackTrace(PrintStream s) {
super.printStackTrace(s);
}
}
अब Expendables
इसे बनाने के लिए कक्षा जाती है:
package chuck;
import javassist.*;
public class Expendables {
private static Class clz;
public static ChuckNorrisException getChuck() {
try {
if (clz == null) {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("chuck.ChuckNorrisException");
cc.setSuperclass(pool.get("java.lang.Object"));
clz = cc.toClass();
}
return (ChuckNorrisException)clz.newInstance();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
और अंत में Main
क्लास को कुछ बट किक करने के लिए:
package chuck;
public class Main {
public void roundhouseKick() throws Exception {
throw Expendables.getChuck();
}
public void foo() {
try {
roundhouseKick();
} catch (Throwable ex) {
System.out.println("Caught " + ex.toString());
}
}
public static void main(String[] args) {
try {
System.out.println("before");
new Main().foo();
System.out.println("after");
} finally {
System.out.println("finally");
}
}
}
निम्नलिखित कमांड के साथ इसे संकलित करें और चलाएं:
java -Xverify:none -cp .:<path_to_javassist-3.9.0.GA.jar> chuck.Main
आपको निम्न आउटपुट मिलेगा:
before
finally
कोई आश्चर्य नहीं - यह एक राउंडहाउस किक है :)
नहीं। जावा में सभी अपवादों को उप-वर्ग होना चाहिए java.lang.Throwable
, और यद्यपि यह अच्छा अभ्यास नहीं हो सकता है, आप हर प्रकार के अपवाद को पकड़ सकते हैं जैसे:
try {
//Stuff
} catch ( Throwable T ){
//Doesn't matter what it was, I caught it.
}
देखें java.lang.Throwable अधिक जानकारी के लिए प्रलेखन।
यदि आप चेक किए गए अपवादों (जिन्हें स्पष्ट रूप से नियंत्रित किया जाना चाहिए) से बचने की कोशिश कर रहे हैं, तो आप त्रुटि, या RuntimeException को उप-वर्ग करना चाहेंगे।
वास्तव में स्वीकृत उत्तर इतना अच्छा नहीं है क्योंकि जावा को सत्यापन के बिना चलाने की आवश्यकता है, अर्थात कोड सामान्य परिस्थितियों में काम नहीं करेगा।
वास्तविक समाधान के लिए बचाव के लिए पहलू !
अपवाद वर्ग:
package de.scrum_master.app;
public class ChuckNorrisException extends RuntimeException {
public ChuckNorrisException(String message) {
super(message);
}
}
पहलू:
package de.scrum_master.aspect;
import de.scrum_master.app.ChuckNorrisException;
public aspect ChuckNorrisAspect {
before(ChuckNorrisException chuck) : handler(*) && args(chuck) {
System.out.println("Somebody is trying to catch Chuck Norris - LOL!");
throw chuck;
}
}
नमूना आवेदन:
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
catchAllMethod();
}
private static void catchAllMethod() {
try {
exceptionThrowingMethod();
}
catch (Throwable t) {
System.out.println("Gotcha, " + t.getClass().getSimpleName() + "!");
}
}
private static void exceptionThrowingMethod() {
throw new ChuckNorrisException("Catch me if you can!");
}
}
आउटपुट:
Somebody is trying to catch Chuck Norris - LOL!
Exception in thread "main" de.scrum_master.app.ChuckNorrisException: Catch me if you can!
at de.scrum_master.app.Application.exceptionThrowingMethod(Application.java:18)
at de.scrum_master.app.Application.catchAllMethod(Application.java:10)
at de.scrum_master.app.Application.main(Application.java:5)
थीम पर एक प्रकार आश्चर्यजनक तथ्य है कि आप जावा कोड से अघोषित जाँच अपवादों को फेंक सकते हैं। चूंकि यह विधियों के हस्ताक्षर में घोषित नहीं है, इसलिए कंपाइलर आपको अपवाद को पकड़ने नहीं देगा, हालांकि आप इसे java.lang.Exception के रूप में पकड़ सकते हैं।
यहाँ एक सहायक वर्ग है जो आपको कुछ भी फेंकने की अनुमति देता है, घोषित या नहीं:
public class SneakyThrow {
public static RuntimeException sneak(Throwable t) {
throw SneakyThrow.<RuntimeException> throwGivenThrowable(t);
}
private static <T extends Throwable> RuntimeException throwGivenThrowable(Throwable t) throws T {
throw (T) t;
}
}
अब throw SneakyThrow.sneak(new ChuckNorrisException());
एक ChuckNorrisException को फेंक देता है, लेकिन संकलक शिकायत करता है
try {
throw SneakyThrow.sneak(new ChuckNorrisException());
} catch (ChuckNorrisException e) {
}
एक अपवाद को पकड़ने के बारे में जो कि फेंक नहीं है अगर ChuckNorrisException एक जाँच अपवाद है।
ChuckNorrisException
जावा में एकमात्र s होना चाहिए OutOfMemoryError
और StackOverflowError
।
आप वास्तव में उन्हें इस अर्थ में "पकड़" सकते हैं कि catch(OutOfMemoryError ex)
अपवाद को फेंक दिए जाने की स्थिति में एक वसीयत निष्पादित होगी, लेकिन वह ब्लॉक स्वचालित रूप से कॉलर को अपवाद को हटा देगा।
मुझे नहीं लगता कि public class ChuckNorrisError extends Error
यह चाल है, लेकिन आप इसे आजमा सकते हैं। मुझे विस्तार के बारे में कोई दस्तावेज नहीं मिलाError
Is it possible to construct a snippet of code in java that would make a hypothetical java.lang.ChuckNorrisException uncatchable?
हां, और यहां उत्तर है: अपना डिजाइन java.lang.ChuckNorrisException
ऐसा बनाएं कि वह इसका उदाहरण न हो java.lang.Throwable
। क्यों? एक अप्राप्य वस्तु परिभाषा के द्वारा उपलब्ध नहीं है क्योंकि आप कभी भी ऐसी चीज नहीं पकड़ सकते जिसे कभी फेंका न जा सके।
java.lang.ChuckNorrisException
को एक अपवाद होना चाहिए, अकेले फेंकने योग्य हो
आप चकोरनिरिस को आंतरिक या निजी रख सकते हैं और उसे एनकैप्सुलेट कर सकते हैं या उसे निगल सकते हैं ...
try { doChuckAction(); } catch(ChuckNorrisException cne) { /*do something else*/ }
जावा में अपवाद हैंडलिंग के साथ दो मूलभूत समस्याएं हैं कि यह इस बात का संकेत देने के लिए अपवाद के प्रकार का उपयोग करता है कि क्या इसके आधार पर कार्रवाई की जानी चाहिए, और जो कुछ भी अपवाद के आधार पर कार्रवाई करता है (यानी "पकड़" तों) इसे हल करने के लिए माना जाता है अंतर्निहित स्थिति। ऐसे साधनों का उपयोग करना उपयोगी होगा जिनके द्वारा एक अपवाद वस्तु तय कर सकती है कि किन हैंडलर को निष्पादित करना चाहिए, और क्या अभी तक निष्पादित हैंडलर ने मौजूदा निकास विधि को पूरा करने के लिए चीजों को साफ किया है। हालांकि इसका उपयोग "अनटचेबल" अपवादों को करने के लिए किया जा सकता है, दो बड़े उपयोग (1) अपवाद बनाने के लिए किए जाएंगे, जिन्हें केवल तब ही हैंडल किया जाएगा जब वे कोड द्वारा पकड़े जाएंगे जो वास्तव में जानते हैं कि उनके साथ कैसे व्यवहार करें,finally
FooException
एक finally
ब्लॉक की अवधि के दौरान BarException
, दोनों अपवादों को कॉल स्टैक का प्रचार करना चाहिए; दोनों को कैच करने योग्य होना चाहिए, लेकिन जब तक दोनों को पकड़ा नहीं जाता है तब तक अन्डरलाइन जारी रहना चाहिए)। दुर्भाग्य से, मुझे नहीं लगता कि चीजों को तोड़े बिना मौजूदा अपवाद-हैंडलिंग कोड काम करने का कोई तरीका होगा।
finally
ब्लॉक पहले के अपवाद से सफाई कर रहा है, तो यह बहुत संभव है कि या तो अपवाद, दूसरे की अनुपस्थिति में, कुछ ऐसा कोड हो सकता है जिस पर कोड को संभालने और जारी रखने की उम्मीद होगी। लेकिन यह कि एक को संभालना और दूसरे की अनदेखी करना बुरा होगा। हालांकि, कोई भी तंत्र नहीं है, एक समग्र अपवाद का उत्पादन करने के लिए कि दोनों हैंडलर प्रक्रिया करेंगे।
Foo
अपवाद के बीच अंतर कर सकता है जो Foo
या तो खुद को फेंक देता है या जानबूझकर इसे नाटक करना चाहता है, खुद को फेंक दिया है, जो Foo
कि होने की उम्मीद नहीं थी। किसी और तरीके से फोन करना। यही "जाँच" अपवादों की धारणा "के बारे में" होनी चाहिए।
वर्तमान थ्रेड पर एक अनकहा अपवाद को अनुकरण करना आसानी से संभव है। यह बिना किसी अपवाद के नियमित व्यवहार को ट्रिगर करेगा, और इस प्रकार कार्य को शब्दार्थ से पूरा करता है। हालांकि, यह जरूरी नहीं कि वर्तमान थ्रेड के निष्पादन को रोकें, क्योंकि वास्तव में कोई अपवाद नहीं फेंका गया है।
Throwable exception = /* ... */;
Thread currentThread = Thread.currentThread();
Thread.UncaughtExceptionHandler uncaughtExceptionHandler =
currentThread.getUncaughtExceptionHandler();
uncaughtExceptionHandler.uncaughtException(currentThread, exception);
// May be reachable, depending on the uncaught exception handler.
यह वास्तव में (बहुत दुर्लभ) स्थितियों में उपयोगी है, उदाहरण के लिए जब उचित Error
हैंडलिंग की आवश्यकता होती है, लेकिन विधि किसी भी फ्रेमवर्क को पकड़ने (और त्यागने) से होती है Throwable
।