Apakah mungkin untuk membuat potongan kode di Jawa yang akan membuat hipotesa tidak cocok java.lang.ChuckNorrisException
?
Pikiran yang datang ke pikiran menggunakan misalnya pencegat atau pemrograman berorientasi aspek .
finalize()
?
Apakah mungkin untuk membuat potongan kode di Jawa yang akan membuat hipotesa tidak cocok java.lang.ChuckNorrisException
?
Pikiran yang datang ke pikiran menggunakan misalnya pencegat atau pemrograman berorientasi aspek .
finalize()
?
Jawaban:
Saya belum mencoba ini, jadi saya tidak tahu apakah JVM akan membatasi sesuatu seperti ini, tapi mungkin Anda bisa mengkompilasi kode yang melempar ChuckNorrisException
, tetapi saat runtime memberikan definisi kelas ChuckNorrisException
yang tidak memperpanjang Throwable .
MEMPERBARUI:
Itu tidak bekerja. Ini menghasilkan kesalahan verifikasi:
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.
PEMBARUAN 2:
Sebenarnya, Anda bisa membuatnya berfungsi jika Anda menonaktifkan verifikasi kode byte! (-Xverify:none
)
PEMBARUAN 3:
Untuk yang mengikuti dari rumah, inilah skrip lengkapnya:
Buat kelas-kelas berikut:
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.");
}
}
}
Kompilasi kelas:
javac -cp . TestVillain.java ChuckNorrisException.java
Lari:
java -cp . TestVillain
Gotcha!
The end.
Mengomentari "extends RuntimeException" dan hanya mengkompilasi ulangChuckNorrisException.java
:
javac -cp . ChuckNorrisException.java
Lari:
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.
Jalankan tanpa verifikasi:
java -Xverify:none -cp . TestVillain
The end.
Exception in thread "main"
Object
bukan Throwable
? (Kompilator tidak akan mengizinkannya, tetapi karena kami telah menonaktifkan verifier, mungkin seseorang dapat meretas bytecode untuk melakukannya.)
Setelah merenungkan ini, saya berhasil membuat pengecualian yang tidak dapat ditandingi. Saya memilih untuk JulesWinnfield
menamainya, daripada Chuck, karena itu adalah salah satu pengecualian ibu-jamur-cloud-laying. Selain itu, mungkin tidak persis apa yang ada dalam pikiran Anda, tetapi tentu saja tidak dapat ditangkap. Mengamati:
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! Pengecualian tanpa tertangkap.
Keluaran:
Lari:
Katakan 'Apa' lagi! Aku menantangmu! Saya gandakan Anda berani!
Hasil Jawa: 8
BUILD SUCCESSFUL (total waktu: 0 detik)
Ketika saya memiliki sedikit waktu lagi, saya akan melihat apakah saya tidak dapat menemukan sesuatu yang lain juga.
Juga, lihat ini:
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)
{
}
}
Menyebabkan stack overflow - lagi, pengecualian tetap tidak tertangkap.
JulesWinfield
? Bukankah sistem akan berhenti melengking sebelum dilempar?
throw new Whatever()
ini benar-benar dua bagian:, Whatever it = new Whatever(); throw it;
dan sistem mati sebelum mencapai bagian kedua.
class cn extends exception{private cn(){}}
Dengan pengecualian seperti itu jelas akan wajib untuk menggunakan System.exit(Integer.MIN_VALUE);
dari konstruktor karena ini adalah apa yang akan terjadi jika Anda melemparkan pengecualian seperti itu;)
while(true){}
bukan System.exit()
.
System.exit()
bekerja dengan menginstal manajer keamanan yang melarangnya. yang akan mengubah konstruktor menjadi pengecualian berbeda (SecurityException), yang dapat ditangkap.
Kode apa pun dapat menangkap Throwable. Jadi tidak, pengecualian apa pun yang Anda buat akan menjadi subkelas Throwable dan akan ditangkap.
hang
berusaha menangkap ChuckNorrisException: P
public class ChuckNorrisException extends Exception {
public ChuckNorrisException() {
System.exit(1);
}
}
(Memang, secara teknis pengecualian ini tidak pernah benar-benar dilemparkan, tetapi suatu hak ChuckNorrisException
tidak dapat dilempar - itu melempar Anda terlebih dahulu.)
Pengecualian apa pun yang Anda lemparkan harus memperpanjang Throwable, sehingga dapat selalu ditangkap. Jadi jawabannya tidak.
Jika Anda ingin membuat sulit untuk menangani, Anda dapat mengganti metode getCause(), getMessage()
, getStackTrace()
, toString()
membuang yang lain java.lang.ChuckNorrisException
.
catch(Throwable t)
hanya menyimpannya ke dalam variabel sehingga saran saya hanya berlaku di blok berikutnya ketika pengguna ingin mengatasi pengecualian
Jawaban saya didasarkan pada ide @ jtahlborn, tetapi ini adalah program Java yang berfungsi penuh , yang dapat dikemas dalam file JAR dan bahkan digunakan untuk server aplikasi favorit Anda sebagai bagian dari aplikasi web .
Pertama-tama, mari kita tentukan ChuckNorrisException
kelas agar tidak crash JVM dari awal (Chuck sangat suka menabrak JVMs 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);
}
}
Sekarang masuk Expendables
kelas untuk membangunnya:
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);
}
}
}
Dan akhirnya Main
kelas menendang pantat:
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");
}
}
}
Kompilasi dan jalankan dengan perintah berikut:
java -Xverify:none -cp .:<path_to_javassist-3.9.0.GA.jar> chuck.Main
Anda akan mendapatkan hasil sebagai berikut:
before
finally
Tidak mengherankan - ini adalah tendangan lokomotif :)
Di konstruktor, Anda dapat memulai utas yang berulang kali memanggil originalThread.stop (ChuckNorisException.this)
Utas dapat menangkap pengecualian berulang kali tetapi akan terus melemparkannya sampai mati.
Tidak. Semua pengecualian di Jawa harus subkelas java.lang.Throwable
, dan meskipun ini mungkin bukan praktik yang baik, Anda dapat menangkap setiap jenis pengecualian seperti:
try {
//Stuff
} catch ( Throwable T ){
//Doesn't matter what it was, I caught it.
}
Lihat java.lang.Terima kasih dokumentasi untuk informasi lebih lanjut.
Jika Anda mencoba untuk menghindari pengecualian yang dicentang (yang harus ditangani secara eksplisit) maka Anda ingin subkelas Kesalahan, atau RuntimeException.
Sebenarnya jawaban yang diterima tidak begitu baik karena Java harus dijalankan tanpa verifikasi, yaitu kode tidak akan berfungsi dalam keadaan normal.
Berusaha menyelamatkan dari solusi nyata !
Kelas pengecualian:
package de.scrum_master.app;
public class ChuckNorrisException extends RuntimeException {
public ChuckNorrisException(String message) {
super(message);
}
}
Aspek:
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;
}
}
Contoh aplikasi:
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!");
}
}
Keluaran:
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)
Varian pada tema adalah fakta mengejutkan bahwa Anda dapat membuang pengecualian yang tidak dideklarasikan dari kode Java. Karena tidak dinyatakan dalam metode signature, kompiler tidak akan membiarkan Anda menangkap pengecualian itu sendiri, meskipun Anda bisa menangkapnya sebagai java.lang.Exception.
Inilah kelas pembantu yang memungkinkan Anda melempar apa saja, dideklarasikan atau tidak:
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;
}
}
Sekarang throw SneakyThrow.sneak(new ChuckNorrisException());
tidak melempar ChuckNorrisException, tetapi kompiler mengeluh
try {
throw SneakyThrow.sneak(new ChuckNorrisException());
} catch (ChuckNorrisException e) {
}
tentang menangkap pengecualian yang tidak dilemparkan jika ChuckNorrisException adalah pengecualian yang diperiksa.
Satu-satunya ChuckNorrisException
di Jawa harus OutOfMemoryError
dan StackOverflowError
.
Anda benar-benar dapat "menangkap" mereka dengan cara yang a catch(OutOfMemoryError ex)
akan dieksekusi dalam kasus pengecualian dilemparkan, tetapi blok itu akan secara otomatis mengubah kembali pengecualian ke penelepon.
Saya tidak berpikir itu berhasil public class ChuckNorrisError extends Error
tetapi Anda bisa mencobanya. Saya tidak menemukan dokumentasi tentang perpanjanganError
Is it possible to construct a snippet of code in java that would make a hypothetical java.lang.ChuckNorrisException uncatchable?
Ya, dan inilah jawabannya: Desain Anda java.lang.ChuckNorrisException
sedemikian rupa sehingga bukan turunan dari java.lang.Throwable
. Mengapa? Objek yang tidak dapat dilewati tidak dapat didefinisikan oleh definisi karena Anda tidak pernah dapat menangkap sesuatu yang tidak pernah dapat dilempar.
java.lang.ChuckNorrisException
harus menjadi pengecualian, apalagi yang bisa dibuang
Anda dapat menjaga ChuckNorris internal atau pribadi dan merangkumnya atau mengikuti ...
try { doChuckAction(); } catch(ChuckNorrisException cne) { /*do something else*/ }
Dua masalah mendasar dengan penanganan pengecualian di Jawa adalah bahwa ia menggunakan tipe pengecualian untuk menunjukkan apakah tindakan harus diambil berdasarkan padanya, dan bahwa apa pun yang mengambil tindakan berdasarkan pengecualian (yaitu "menangkap" itu) dianggap untuk menyelesaikan kondisi yang mendasarinya. Akan bermanfaat untuk memiliki sarana yang dengannya objek pengecualian dapat memutuskan penangan mana yang harus dieksekusi, dan apakah penangan yang telah mengeksekusi sejauh ini telah membersihkan hal-hal yang cukup untuk metode ini untuk memenuhi kondisi keluarnya. Meskipun ini dapat digunakan untuk membuat pengecualian "tak tertandingi", dua kegunaan yang lebih besar adalah (1) membuat pengecualian yang hanya akan dianggap ditangani ketika mereka ditangkap oleh kode yang benar-benar tahu cara menghadapinya,finally
FooException
finally
blok selama pelepasan a BarException
, kedua pengecualian harus merambat ke tumpukan panggilan; keduanya harus dapat ditangkap, tetapi pelonggaran harus berlanjut sampai keduanya tertangkap). Sayangnya, saya tidak berpikir akan ada cara untuk membuat kode penanganan eksepsi yang ada berfungsi seperti itu tanpa merusak barang-barang.
finally
blok membersihkan dari pengecualian sebelumnya, sangat mungkin bahwa salah satu pengecualian, tanpa adanya yang lain, mungkin sesuatu yang diharapkan akan ditangani oleh kode dan dilanjutkan, tetapi menangani satu dan mengabaikan yang lain akan buruk. Namun, tidak ada mekanisme untuk menghasilkan pengecualian gabungan yang akan diproses oleh kedua penangan.
Foo
dapat membedakan antara pengecualian yang Foo
melemparkan sendiri atau sengaja ingin berpura-pura melemparkan sendiri, dari yang Foo
tidak diharapkan terjadi ketika itu memanggil beberapa metode lain. Itulah yang seharusnya menjadi pengecualian "dicentang".
Sangat mudah untuk mensimulasikan pengecualian yang tidak tertangkap pada utas saat ini. Ini akan memicu perilaku reguler pengecualian yang tidak tertangkap, dan dengan demikian menyelesaikan pekerjaan secara semantik. Namun, itu tidak akan menghentikan eksekusi utas saat ini, karena tidak ada pengecualian yang benar-benar dilemparkan.
Throwable exception = /* ... */;
Thread currentThread = Thread.currentThread();
Thread.UncaughtExceptionHandler uncaughtExceptionHandler =
currentThread.getUncaughtExceptionHandler();
uncaughtExceptionHandler.uncaughtException(currentThread, exception);
// May be reachable, depending on the uncaught exception handler.
Ini sebenarnya berguna dalam situasi (sangat jarang), misalnya ketika Error
penanganan yang tepat diperlukan, tetapi metode ini diambil dari kerangka kerja menangkap (dan membuang) apa pun Throwable
.