Java'da bir varsayımı java.lang.ChuckNorrisException
erişilemez kılacak bir kod snippet'i oluşturmak mümkün müdür?
Akla gelen düşünceler, örneğin önleyici veya en boy yönelimli programlama kullanıyor .
finalize()
?
Java'da bir varsayımı java.lang.ChuckNorrisException
erişilemez kılacak bir kod snippet'i oluşturmak mümkün müdür?
Akla gelen düşünceler, örneğin önleyici veya en boy yönelimli programlama kullanıyor .
finalize()
?
Yanıtlar:
Eğer bilmiyorum bu yüzden, bu denemedim JVM böyle bir şey kısıtlayacak, ama belki atar kodunu derlemek olabilir ChuckNorrisException
, ama zamanında bir sınıf tanımını sağlamak ChuckNorrisException
hangi Throwable kapsamaz .
GÜNCELLEME:
Çalışmıyor. Doğrulayıcı hatası oluşturur:
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.
GÜNCELLEME 2:
Aslında, bayt kodu doğrulayıcıyı devre dışı bırakırsanız bunu çalıştırabilirsiniz! ( -Xverify:none
)
GÜNCELLEME 3:
Evden takip edenler için tam komut dosyası:
Aşağıdaki sınıfları oluşturun:
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.");
}
}
}
Sınıfları derleyin:
javac -cp . TestVillain.java ChuckNorrisException.java
Çalıştırmak:
java -cp . TestVillain
Gotcha!
The end.
"RuntimeException'ı genişletir" ve yalnızca yeniden derleyinChuckNorrisException.java
:
javac -cp . ChuckNorrisException.java
Çalıştırmak:
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.
Doğrulama olmadan çalıştır:
java -Xverify:none -cp . TestVillain
The end.
Exception in thread "main"
Object
yerine onu yakalarsan Throwable
? (Derleyici buna izin vermez, ancak doğrulayıcıyı zaten devre dışı bıraktığımız için, belki bayt kodunu bunu yapmak için hacklenebilir.)
Bunu düşündükten sonra başarıyla yakalanamayan bir istisna oluşturdum. JulesWinnfield
Bununla birlikte, Chuck yerine ad vermeyi seçtim , çünkü bu bir mantar-bulut-döşeme-anne-istisnası. Dahası, tam olarak aklınızdakiler olmayabilir, ama kesinlikle yakalanamaz. Gözlemek:
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");
}
}
Et voila! Yakalanmamış istisna.
Çıktı:
Çalıştırmak:
Tekrar 'Ne' deyin! Sana meydan okuyorum! Sana iki kez cüret ediyorum!
Java Sonucu: 8
BAŞARILI OLUŞTUR (toplam süre: 0 saniye)
Biraz daha zamanım olduğunda, başka bir şey daha bulup bulamayacağımı göreceğim.
Ayrıca, şuna da göz atın:
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)
{
}
}
Yığın taşmasına neden olur - yine istisnalar yakalanmaz.
JulesWinfield
? Sistem atılmadan önce çığlık atmayacak mı?
throw new Whatever()
gerçekten iki Whatever it = new Whatever(); throw it;
kısımdır : ve sistem ikinci kısma ulaşmadan ölür.
class cn extends exception{private cn(){}}
Böyle bir istisna dışında, kurucudan bir kullanmak zorunludur, System.exit(Integer.MIN_VALUE);
çünkü böyle bir istisna fırlatırsanız ne olur;)
while(true){}
yerine kullanabilirsiniz System.exit()
.
System.exit()
onu izin vermeyen bir güvenlik yöneticisi yükleyerek çalışmaktan. yapıcıyı yakalanabilecek farklı bir istisnaya (SecurityException) dönüştürür.
Herhangi bir kod Throwable yakalayabilir. Yani hayır, yarattığınız istisna ne olursa olsun Throwable'ın bir alt sınıfı olacak ve yakalanmaya tabi olacak.
hang
yakalamak ChuckNorrisException amacıyla kendisi: P
public class ChuckNorrisException extends Exception {
public ChuckNorrisException() {
System.exit(1);
}
}
( Teknik olarak, bu istisna asla gerçekte atılmaz, ancak uygun bir şekilde ChuckNorrisException
atılamaz - önce sizi atar.)
Attığınız herhangi bir istisna Throwable'ı genişletmelidir, böylece her zaman yakalanabilir. Yani cevap hayır.
Size zor işlemek için yapmak istiyorsanız, yöntemleri geçersiz kılabilir getCause(), getMessage()
, getStackTrace()
, toString()
başka atmak java.lang.ChuckNorrisException
.
catch(Throwable t)
sadece değişkene depolar, bu yüzden önerilerim sadece kullanıcı istisna ile başa çıkmak istediğinde sonraki blokta geçerlidir
Cevabım @ jtahlborn'un fikrine dayanıyor, ancak bir JAR dosyasına paketlenebilen ve hatta bir web uygulamasının parçası olarak favori uygulama sunucunuza dağıtılabilen tamamen çalışan bir Java programı .
Her şeyden önce, ChuckNorrisException
sınıfı tanımlayalım, böylece JVM'yi en başından çökmeyecek (Chuck gerçekten JVM'lerin çökmesini seviyor BTW :)
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);
}
}
Şimdi Expendables
onu inşa etmek için sınıfa gidiyor :
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);
}
}
}
Ve sonunda Main
sınıf bir popoyu tekmelemek için:
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");
}
}
}
Derleyin ve aşağıdaki komutla çalıştırın:
java -Xverify:none -cp .:<path_to_javassist-3.9.0.GA.jar> chuck.Main
Aşağıdaki çıktıyı alacaksınız:
before
finally
Sürpriz değil - sonuçta bir cezaevi tekme :)
Yapıcıda tekrar tekrar çağıran bir iş parçacığı başlatabilirsiniz originalThread.stop (ChuckNorisException.this)
İplik istisnayı tekrar tekrar yakalayabilir, ancak ölene kadar atmaya devam eder.
Hayır. Java'daki tüm istisnalar alt sınıf olmalıdır java.lang.Throwable
ve iyi bir uygulama olmamasına rağmen, aşağıdaki gibi her türlü istisnayı yakalayabilirsiniz:
try {
//Stuff
} catch ( Throwable T ){
//Doesn't matter what it was, I caught it.
}
Daha fazla bilgi için java.lang.Throwable belgelerine bakın .
İşaretli istisnalardan (açıkça işlenmesi gereken) kaçınmaya çalışıyorsanız, Hata veya RuntimeException alt sınıflarını kullanmak istersiniz.
Aslında kabul edilen cevap çok hoş değil, çünkü Java'nın doğrulama olmadan çalıştırılması gerekiyor, yani kod normal koşullar altında çalışmayacaktı.
AspectJ gerçek çözüm için kurtarmaya !
İstisna sınıfı:
package de.scrum_master.app;
public class ChuckNorrisException extends RuntimeException {
public ChuckNorrisException(String message) {
super(message);
}
}
Görünüş:
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;
}
}
Örnek uygulama:
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!");
}
}
Çıktı:
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)
Temanın bir varyasyonu, Java kodundan bildirilmemiş kontrol edilmiş istisnalar atabileceğiniz şaşırtıcı bir gerçektir. Yöntemler imzasında bildirilmediğinden, derleyici istisnayı kendisi yakalamanıza izin vermez, ancak java.lang.Exception olarak yakalayabilirsiniz.
Aşağıda, beyan edilmiş olsun veya olmasın, herhangi bir şey atmanıza izin veren bir yardımcı sınıf:
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;
}
}
Şimdi throw SneakyThrow.sneak(new ChuckNorrisException());
bir ChuckNorrisException atıyor, ancak derleyici
try {
throw SneakyThrow.sneak(new ChuckNorrisException());
} catch (ChuckNorrisException e) {
}
ChuckNorrisException denetlenmiş bir özel durumsa atılan bir özel durumu yakalama hakkında.
Sadece ChuckNorrisException
Java s olmalıdır OutOfMemoryError
ve StackOverflowError
.
catch(OutOfMemoryError ex)
İstisna fırlatılması durumunda bir yürütmenin gerçekleştirileceği anlamına gelebilir, ancak bu blok istisnayı otomatik olarak arayan kişiye yeniden gönderir.
Bunun public class ChuckNorrisError extends Error
hile yaptığını sanmıyorum ama siz de deneyebilirsiniz. Uzatma hakkında hiçbir belge bulamadımError
Is it possible to construct a snippet of code in java that would make a hypothetical java.lang.ChuckNorrisException uncatchable?
Evet, işte cevabı: java.lang.ChuckNorrisException
Öyle bir örnek olmayacak şekilde tasarlajava.lang.Throwable
. Neden? İzlenemeyen bir nesne tanım gereği erişilemez çünkü asla atılamayacak bir şey yakalayamazsınız.
java.lang.ChuckNorrisException
bir istisna olması gerektiği konusunda hiçbir yer bulamıyorum , yalnız atılabilir
ChuckNorris'i dahili veya özel tutabilir ve onu kapsülleyebilir veya takip edebilirsiniz ...
try { doChuckAction(); } catch(ChuckNorrisException cne) { /*do something else*/ }
Java'da özel durum işleme ile ilgili iki temel sorun, eylemin buna dayalı olarak gerçekleştirilip gerçekleştirilmeyeceğini belirtmek için bir istisna türü kullanması ve bir istisnayı temel alarak eylem yapan herhangi bir şeyin (yani "yakala") çözüleceği varsayılmasıdır. altta yatan durum. Bir istisna nesnesinin hangi işleyicilerin yürütmesi gerektiğine ve şimdiye kadar yürütülen işleyicilerin mevcut yöntemin çıkış koşullarını karşılaması için yeterince temizleyip temizlemediğine karar verebileceği bir araca sahip olmak faydalı olacaktır. Bu "yakalanamayan" istisnalar yapmak için kullanılabilse de, (1) yalnızca onlarla nasıl başa çıkılacağını gerçekten bilen bir kod tarafından yakalandıklarında ele alınacak istisnalar yapmak olmak için iki büyük kullanım olacaktır,finally
FooException
finally
a'nın çözülmesi sırasında bir blok sırasında BarException
, her iki istisna da çağrı yığınını yaymalıdır; her ikisi de yakalanabilir olmalıdır, ancak her ikisi yakalanana kadar gevşemeye devam edilmelidir). Ne yazık ki, mevcut istisna işleme kodunu işleri bozmadan bu şekilde çalıştırmanın herhangi bir yolu olacağını düşünmüyorum.
finally
blok daha önceki bir istisnayı temizlerken bir istisna oluşursa , her iki istisnanın da diğerinin yokluğunda kodun işlemesini ve devam etmesini bekleyeceği bir şey olması mümkündür, ama birini idare etmek ve diğerini görmezden gelmek kötü olur. Bununla birlikte, her iki işleyicinin işleyeceği bileşik bir istisna üretecek bir mekanizma yoktur.
Foo
bir istisna arasında ayrım yapabileceği bir araç olması gerektiğidir , başka bir yöntem çağırıyor. "Kontrol edilen" istisnalar kavramı "hakkında" olmalıdır. Foo
Foo
Mevcut iş parçacığında yakalanmamış bir istisnayı simüle etmek kolayca mümkündür. Bu, yakalanmamış bir istisnanın düzenli davranışını tetikler ve böylece işi anlamsal olarak yapar. Ancak, gerçekte bir istisna olmadığı için geçerli iş parçacığının yürütülmesini durdurması gerekmez.
Throwable exception = /* ... */;
Thread currentThread = Thread.currentThread();
Thread.UncaughtExceptionHandler uncaughtExceptionHandler =
currentThread.getUncaughtExceptionHandler();
uncaughtExceptionHandler.uncaughtException(currentThread, exception);
// May be reachable, depending on the uncaught exception handler.
Bu aslında (çok nadir) durumlarda, örneğin uygun Error
kullanım gerektiğinde yararlıdır , ancak yöntem herhangi bir çerçeveyi yakalayan (ve atayan) bir çerçeveden çağrılır Throwable
.