nullpointerexceptionn in nullpointerexceptionn handler 怎么解决

developerWorks 社区
跟踪无法预期的运行时异常可能是一件又慢又费力的事情,只获得默认线程名称和堆栈跟踪通常是不够的。在
驯服 Tiger 这一期专栏中,Java 开发人员 John Zukowski 向您展示了如何通过替代默认行为来定制输出。他还对比了通过细分
ThreadGroup 定制输出的老方法与通过提供自己的
UncaughtExceptionHandler 定制输出的新方法。
(), 总裁, JZ Ventures, Inc.
John Zukowski 为
做战略性 Java 咨询,并与
合作开发下一代移动电话平台。他最近的著作有
(Sybex,2002 年 4 月)和
(Apress,2002 年 3 月)。您可以通过
与 John 联系。
虽然我们不想创建在无法预期时抛出运行时异常的程序,但这种情况还是会发生——尤其是第一次运行复杂程序时。通常是使用默认行为、打印堆栈溢出和结束线程的生命来处理这些异常。从哪里发现默认行为?每个线程都属于一个由
java.lang.ThreadGroup 类表示的线程组。顾名思义,线程组允许您将线程组合在一起。您可能是为了方便而将线程组合,例如,一个线程池中的所有线程都属于组 X,而另一个池的所有线程则属于组 Y,或者是为了访问控制而将线程进行组合。组 X 中的线程无权访问或改变组 Y 中的线程,除非它们都在同一线程组内(或在一个子组内)。
在 Tiger 之前,
ThreadGroup 类提供了一种处理未捕获异常的方法:
ThreadGroup 的
uncaughtException() 方法。如果异常不是
ThreadDeath ,则将线程的名称和堆栈回溯(stack backtrace)发送到
System.err 。但是 Tiger 添加了另一种方法:
Thread.UncaughtExceptionHandler 接口。细分
ThreadGroup 或安装该新接口的实现都允许您更改默认行为。我们将对 Tiger 之前和之后提供的方法都进行研究。
使用 ThreadGroup 的定制行为发生未捕获的异常时,默认行为是将堆栈溢出打印输出到系统错误(
System.err )中,如清单 1 中所示。不需要使用任何命令参数来启动程序。
清单 1. 线程溢出示例public class SimpleDump {
public static void main(String args[]) {
System.out.println(args[0]);
}不使用任何参数运行该程序将生成清单 2 中的输出。尽管它不是一个很长的堆栈跟踪,但它是一个完整的堆栈跟踪。清单 2. 默认线程溢出输出Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at SimpleDump.main(SimpleDump.java:3)正如 Java 平台的许多东西一样,如果不喜欢默认行为,您可以对其进行更改。在 Java 平台的 Tiger 版以前的版本中,不能替代所有线程的默认行为,但是可以创建一个新的
ThreadGroup ,并更改在该组内创建的任何线程的默认行为。您可以重写
uncaughtException(Thread t, Throwable e) 方法来定制该行为。然后,当发生未预料的运行时异常时,该线程组内创建的任何线程都将获得新的行为。不过,最好是修复基础问题,我将提供一个简单的示例,说明更改默认行为所必需的步骤。清单 3 展示了将执行代码放入新线程的调整过的测试程序:
清单 3. 调整过的线程溢出示例public class WindowDump {
public static void main(String args[]) throws Exception {
ThreadGroup group = new LoggingThreadGroup("Logger");
new Thread(group, "myThread") {
public void run() {
System.out.println(1 / 0);
}.start();
}LoggingThreadGroup 类是一个新的内容,清单 4 中显示了它的定义。为了进行说明,通过重写
uncaughtException() 方法实现的特殊行为将在一个弹出窗口中显示该异常,这项操作是在特殊
Handler 的帮助下使用 Java Logging API 来完成的。
清单 4. LoggingThreadGroup 的定义import java.util.logging.*;
public class LoggingThreadGroup extends ThreadGroup {
private static L
public LoggingThreadGroup(String name) {
super(name);
public void uncaughtException(Thread t, Throwable e) {
// Initialize logger once
if (logger == null) {
logger = Logger.getLogger("example");
Handler handler = LoggingWindowHandler.getInstance();
logger.addHandler(handler);
logger.log(Level.WARNING, t.getName(), e);
}这里创建的定制
Handler 的类型为
LoggingWindowHandler ,该类型的定义在清单 5 中。处理程序使用了一个支持类
LoggingWindow ,该类将异常显示在屏幕上。
中显示了该类的定义。
Handler 的
public void publish(LogRecord record) 方法实现了一些重要操作。其余操作大部分只与配置有关。
清单 5. LoggingWindowHandler 的定义import java.util.logging.*;
public class LoggingWindowHandler extends Handler {
private static LoggingW
private static LoggingWindowH
private LoggingWindowHandler() {
configure();
window = new LoggingWindow("Logging window...", 400, 200);
public static synchronized LoggingWindowHandler getInstance() {
if (handler == null) {
handler = new LoggingWindowHandler();
* Get any configuration properties set
private void configure() {
LogManager manager = LogManager.getLogManager();
String className = getClass().getName();
String level = manager.getProperty(className + ".level");
setLevel((level == null) ?
: Level.parse(level));
String filter = manager.getProperty(className + ".filter");
setFilter(makeFilter(filter));
String formatter =
manager.getProperty(className + ".formatter");
setFormatter(makeFormatter(formatter));
private Filter makeFilter(String name) {
Filter f =
Class c = Class.forName(name);
f = (Filter)c.newInstance();
} catch (Exception e) {
if (name != null) {
System.err.println("Unable to load filter: " + name);
private Formatter makeFormatter(String name) {
Formatter f =
Class c = Class.forName(name);
f = (Formatter)c.newInstance();
} catch (Exception e) {
f = new SimpleFormatter();
// Overridden abstract Handler methods
public void close() {
public void flush() {
* If record is loggable, format it and add it to window
public void publish(LogRecord record) {
String message =
if (isLoggable(record)) {
message = getFormatter().format(record);
} catch (Exception e) {
reportError(null, e, ErrorManager.FORMAT_FAILURE);
window.addLogInfo(message);
} catch (Exception e) {
reportError(null, e, ErrorManager.WRITE_FAILURE);
}清单 6. LoggingWindow 的定义import java.awt.*;
import javax.swing.*;
public class LoggingWindow extends JFrame {
private JTextArea textA
public LoggingWindow(String title, final int width,
final int height) {
super(title);
EventQueue.invokeLater(new Runnable() {
public void run() {
setSize(width, height);
textArea = new JTextArea();
JScrollPane pane = new JScrollPane(textArea);
textArea.setEditable(false);
getContentPane().add(pane);
setVisible(true);
public void addLogInfo(final String data) {
EventQueue.invokeLater(new Runnable() {
public void run() {
textArea.append(data);
WindowDump 程序将出现图 1 中的屏幕。因为没有从
Logger 中删除控制台处理程序,所以堆栈溢出仍将出现在控制台上。
图 1. 记录的堆栈跟踪发生运行时异常时,可能要做许多工作来更改发生的问题。该代码的大部分都是 Logging Handler,但是,要执行更改,就必须细分
ThreadGroup ,重写
uncaughtException() ,然后在该线程组中执行您的线程。不过,让我们通过只安装
Thread.UncaughtExceptionHandler ,来看一看 Tiger 的处理方式。
使用 UncaughtExceptionHandler 的定制行为对于 Tiger,
Thread 类定义中添加了一个新的公共内部类
UncaughtExceptionHandler ,更完整的名称为
Thread.UncaughtExceptionHandler (其他类访问内部类时需要使用完整名称)。接口的定义是一个方法,如图 7 中所示:
清单 7. UncaughtExceptionHandler 的定义public interface Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread, Throwable);
}您可能没有注意到,清单 7 中的方法与我们前面重写的
ThreadGroup 的方法相同。实际上,现在由
ThreadGroup 类实现该接口。
新的内部类可以帮助我们了解下列两对新方法,并有助于我们在
Thread 中使用它们:
getUncaughtExceptionHandler() 和
setUncaughtExceptionHandler() 。
getDefaultUncaughtExceptionHandler() 和
setDefaultUncaughtExceptionHandler() 。
第一对方法是
getUncaughtExceptionHandler() 和
setUncaughtExceptionHandler() ,它们允许您为当前线程及其后代定制行为,从而允许二十或更多的线程拥有自己的定制行为。不过,您更可能使用第二对方法
getDefaultUncaughtExceptionHandler() 和
setDefaultUncaughtExceptionHandler() 。如果使用第二对方法设置默认处理程序,那么没有自己的异常处理程序的所有线程都将使用默认处理程序。
听起来好像很简单。为了进行说明,清单 8 转换了
ThreadGroup 友好的程序,使用新的
UncaughtExceptionHandler 接口:
清单 8. UncaughtExceptionHandler 示例public class HandlerDump {
public static void main(String args[]) throws Exception {
Thread.UncaughtExceptionHandler handler = new LoggingThreadGroup("Logger");
Thread.currentThread().setUncaughtExceptionHandler(handler);
System.out.println(1 / 0);
}该程序只是将
LoggingThreadGroup 重用为
UncaughtExceptionHandler ,并没有创建新的处理程序实现。请注意,与原来的代码相比,新代码要简洁得多。
其他线程更改Thread 类不仅支持使用 Tiger 添加的未捕获异常处理程序,它还支持使用
getAllStackTraces() 获得所有有效线程的堆栈跟踪,或者支持使用
getStackTrace() 来只获得当前线程的堆栈跟踪。这两种堆栈跟踪都返回类型为
java.lang.StackTraceElement 的对象,
java.lang.StackTraceElement 是 Java 1.4 平台中添加的一个类,它可以让您生成自己的堆栈跟踪。同时,Java 5 平台新添加的功能是一个惟一线程标识符(可以使用
getId() 获得该标识符)和一个新的
Thread.State 类,以及与该类相关的
getThreadState() 方法。最后一个线程更改是一个状态枚举表,该表是用来监视系统状态,而不是用来同步状态的。
结束语像添加未捕获的异常处理程序这样的简单库更改,可以极大地增加原代码的可理解性。虽然在线程组级别上,新的库代码的功能与原来库代码的相同,但新模型中的易用性和灵活性远远超出了将代码调整为更新的方式所需的时间。当然,老方法仍然可以使用,但最好将代码更新为最新的库功能。
下载描述名字大小---
参考资料 您可以参阅本文在 developerWorks 全球站点上的
阅读 John Zukowski 的全部
单击本文顶部或底部的
代码图标来下载本文中的代码示例。
从 Sun Developer Network 下载
类的 javadoc。
类的 Javadoc。
阅读 Java 5 平台的
包的 javadoc。
从 Brian Goetz 的
Java theory and practice专栏的“
developerWorks,2002 年 9 月)中学习如何避免服务器应用程序中的线程泄露。
developerWorks,2002 年 9 月)中学习线程处理的原则。
Magic with Merlin专栏的“
developerWorks,2001 年 12 月)中学习 Logging API。
检验 Tiger (J2SE 5) 的一些改进。
用电子邮件向 Sun 报告 bug。
可以找到数百种关于 Java 技术的参考资料。
,获得技术书籍的完整列表,其中包括数百篇
developerWorks: 登录
标有星(*)号的字段是必填字段。
保持登录。
单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件。
在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。
所有提交的信息确保安全。
选择您的昵称
当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。昵称长度在 3 至 31 个字符之间。
您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。
标有星(*)号的字段是必填字段。
(昵称长度在 3 至 31 个字符之间)
单击提交则表示您同意developerWorks 的条款和条件。 .
所有提交的信息确保安全。
IBM PureSystems(TM) 系列解决方案是一个专家集成系统
通过学习路线图系统掌握软件开发技能
软件下载、试用版及云计算
static.content.url=/developerworks/js/artrating/SITE_ID=10Zone=Java technologyArticleID=54624ArticleTitle=驯服 Tiger: 线程中的默认异常处理publish-date=Keyboard Shortcuts?
Next menu item
Previous menu item
Previous man page
Next man page
Scroll to bottom
Scroll to top
Goto homepage
Goto search(current page)
Focus search box
Change language:
Brazilian Portuguese
Chinese (Simplified)
set_exception_handler
set_exception_handler &
设置一个用户定义的异常处理函数。
set_exception_handler
$exception_handler
exception_handler
当一个未捕获的异常发生时所调用函数的名称。
该函数必须在调用 set_exception_handler() 之前已经定义。
该处理函数需要接受一个参数,该参数是一个抛出的异常对象。
也可以传递一个 NULL 值用于重置异常处理函数为默认值。
返回之前定义的异常处理程序的名称,或者在错误时返回 NULL。
如果之前没有定义一个错误处理程序,也会返回 NULL。
如果参数使用了 NULL,重置处理程序为默认状态,并且会返回一个 TRUE。
Example #1 set_exception_handler() 范例
&?phpfunction&exception_handler($exception)&{&&echo&"Uncaught&exception:&"&,&$exception-&getMessage(),&"\n";}set_exception_handler('exception_handler');throw&new&Exception('Uncaught&Exception');echo&"Not&Executed\n";?&
- 恢复之前定义过的异常处理函数。
- 还原之前的错误处理函数
- 设置应该报告何种 PHP 错误
类型的信息
Things you should be aware of:An exception handler handles exceptions that were not caught before. It is the nature of an exception that it discontinues execution of your program - since it declares an exceptional situation in which the program cannot continue (except you catch it).Since it has not been catched your code signals it is not being aware of the situation and cant go on.This implies: returning to the script is simply impossible when the exception handler has already been called, since an uncaught exception is not a notice. use your own debug- or notice-log-system for things like that.Furthermore: While is is still possible to call functions from your script, since the exception handler has already been called exceptions bubbling from that piece of code won't trigger the exception handler again. php will die without leaving any information apart form "uncaught exception with unknown stack frame". So if you call functions from your script, make sure that you catch any exceptions that possibly occur via try..catch inside the exception handler.For those of you who misinterpreted the essential meaning of the exception handler: it's only use is to handle the abortion of your script gracefully, e.g. in a project like facebook or wikipedia: render a nice error page, eventually hiding information which shall not leak into the public (instead you may want to write to your log or mail the sys-admin or stuff like that).In other words: Redirecting all php-errors form an error-handler using exceptions - including notices - is a very dumb idea, if you do not intend having your script aborted everytime you didn't set a variable (for example).my 2 cents.
A behaviour not documented or discussed enough, yet pretty common is that is that if an exception is thrown from the global exception handler then a fatal error occurs (Exception thrown without a stack frame). That is, if you define your own global exception handler by calling set_exception_handler() and you throw an exception from inside it then this fatal error occurs. It is only natural though, as the callback defined by set_exception_handler() is only called on uncaught (unhandled) exceptions so if you throw one from there then you get this fatal error as there is no exception handler left (you override the php internal one by calling set_exception_handler()), hence no stack frame for it.Example:&?phpfunction myExceptionHandler (Exception $ex){& & throw $ex;}set_exception_handler("myExceptionHandler");throw new Exception("This should cause a fatal error and this message will be lost");?&Will cause a Fatal error: Exception thrown without a stack frameIf you skip/comment the set_exception_handler("...") line then the internal PHP global handler will catch the exception and output the exception message and trace (as string) to the browser, allowing you to at least see the exception message.While it is a very good idea to always define your own global exception handler by using the set_exception_handler() function, you should pay attention and never throw an exception from it (or if you do then catch it).Finally, every serious coder should use an IDE with debugging capabilities. Tracking down an error like this becomes a trivial matter by using simple debugging "Step into" commands (I for one recommend Zend IDE v5.2 at the moment of this writing). I have seen numerous messages on the internet with people wondering why this message pops up.Cheersp.s. Other causes for this error which are somehow unrelated to this is when you throw an exception from a destructor (the reasons behind that are similar though, the global handler might no longer exist due to the php engine shutting the page down).
Thanks to mastabog we know that throwing an exception within the exception handler will trigger a fatal error and a debugging nightmare.& To avoid throwing an exception within there should be easy.However, if you use a custom error handler to convert errors to ErrorExceptions suddenly there are a multitude of new ways to accidentally throw exceptions within the exception handler.&?phpfunction error_handler($code, $message, $file, $line){& & if (0 == error_reporting())& & {& & & && & }& & throw new ErrorException($message, 0, $code, $file, $line);}function exception_handler($e){& & print $undefined; }set_error_handler("error_handler");set_exception_handler("exception_handler");throw new Exception("Just invoking the exception handler");?&Output: Fatal error: Exception thrown without a stack frame in Unknown on line 0The best way I have found to avoid this is to wrap up everything in the exception handler in a try/catch block.&?phpfunction exception_handler($e){& & try& & {& & & & print $undefined; }& & catch (Exception $e)& & {& & & & print get_class($e)." thrown within the exception handler. Message: ".$e-&getMessage()." on line ".$e-&getLine();& & }}?&Output: ErrorException thrown within the exception handler. Message: Undefined variable: undefined on line 14This speeds up debugging and offers some scalability to any other exceptions accidentally thrown within the exception handler.Another solution is to restore the error handler at the beginning of the exception handler.& While this is a silver bullet in terms of avoiding the ErrorExceptions, debugging messages then rely on the error_reporting() level and the display_errors directive.& Why mention this?& It might be preferable for production code since we care more about hiding errors from users than convenient debugging messages.
If you're handling sensitive data and you don't want exceptions logging details such as variable contents when you throw them, you may find yourself frustratedly looking for the bits and pieces that make up a normal stack trace output, so you can retain its legibility but just alter a few things. In that case, this may help you:&?phpfunction exceptionHandler($exception) {& & $traceline = "#%s %s(%s): %s(%s)";& & $msg = "PHP Fatal error:& Uncaught exception '%s' with message '%s' in %s:%s\nStack trace:\n%s\n& thrown in %s on line %s";& & $trace = $exception-&getTrace();& & foreach ($trace as $key =& $stackPoint) {& & & & $trace[$key]['args'] = array_map('gettype', $trace[$key]['args']);& & }& & $result = array();& & foreach ($trace as $key =& $stackPoint) {& & & & $result[] = sprintf(& & & & & & $traceline,& & & & & & $key,& & & & & & $stackPoint['file'],& & & & & & $stackPoint['line'],& & & & & & $stackPoint['function'],& & & & & & implode(', ', $stackPoint['args'])& & & & );& & }& & $result[] = '#' . ++$key . ' {main}';& & $msg = sprintf(& & & & $msg,& & & & get_class($exception),& & & & $exception-&getMessage(),& & & & $exception-&getFile(),& & & & $exception-&getLine(),& & & & implode("\n", $result),& & & & $exception-&getFile(),& & & & $exception-&getLine()& & );& & error_log($msg);}?&If you're not a fan of sprintf() or the duplicate $exception-&getFile() and $exception-&getLine() calls you can of course replace that as you like - consider this a mere compilation of the parts.
On GNU/Linux, When an exception handler is called, PHP will end with exit status code 0 instead of 255.You can change the exit status code with an exit() call at the end of your custom error handler.
frank,Your exception handler is configured to be the handler for all exceptions, yet if a basic 'Exception' is thrown, your static method will error because 'Exception's do not have 'getException'.& Because of this I don't see a real purpose to making the uncaught handler a class that extends Exception.& I do like the idea of using static methods of a general Exception handling class.& &?phpclass ExceptionHandler {&& & & public static function printException(Exception $e)& & {& & & & print 'Uncaught '.get_class($e).', code: ' . $e-&getCode() . "&br /&Message: " . htmlentities($e-&getMessage())."\n";& & }&& & & public static function handleException(Exception $e)& & {& & & && self::printException($e);& & }}set_exception_handler(array("ExceptionHandler", "handleException"));class NewException extends Exception {}try {& throw new NewException("Catch me once", 1);} catch (Exception $e) {& ExceptionHandler::handleException($e);}throw new Exception("Catch me twice", 2);?&Gives:Uncaught NewException, code: 1&br /&Message: Catch me onceUncaught Exception, code: 2&br /&Message: Catch me twiceThere are much more interesting things that can be done like reformating and optionally displaying or emailing them.& But this class acts a nice container for those functions.
If you want a class instance to handle the exception, this is how you do it :&?phpclass example {&& public function __construct() {& & && @set_exception_handler(array($this, 'exception_handler'));& & && throw new Exception('DOH!!');&& }&& public function exception_handler($exception) {& & && print "Exception Caught: ". $exception-&getMessage() ."\n";&& }}$example = new example;?&See the first post (Sean's) for a static example.& As Sean points out, the exception_handler function must be declared public.
I've been messing around with this function, and have noticed you can pass an anonymous function (created with create_function()) through as the default handler, for example:set_exception_handler(create_function('$e', 'exit("An unknown error occurred");'));That snippet of code can be used if you simply want to suppress all exceptions that are not handled.& This can be a great thing, because secure data could possibly be leaked otherwise (for example, the default exception handler could output a snippet of your SQL code that was involved with the exception being thrown).You will want to use this wisely, however (if at all).
By default the stack trace is pretty unreadable, so you might want to wrap it in &pre& tags. Here I also wrap it in a &div& and set the class 'alert alert-danger' which are CSS classes in the Bootstrap CSS framework to style them red.&?phpfunction exception_handler($exception) {& echo '&div class="alert alert-danger"&';& echo '&b&Fatal error&/b&:& Uncaught exception \'' . get_class($exception) . '\' with message ';& echo $exception-&getMessage() . '&br&';& echo 'Stack trace:&pre&' . $exception-&getTraceAsString() . '&/pre&';& echo 'thrown in &b&' . $exception-&getFile() . '&/b& on line &b&' . $exception-&getLine() . '&/b&&br&';& echo '&/div&';}set_exception_handler('exception_handler');
This seems not to work when calling the PHP binary with the '-r' flag.For example, if I run it like this:& & php -r '& & & function exception_handler($exception) {& & & & echo "Uncaught exception: " , $exception-&getMessage(), "\n";& & & } & & & set_exception_handler("exception_handler"); & & & throw new Exception("Uncaught Exception");& & & echo "Not Executed\n";& & 'Or if I place it in a file and run it like this:& & php -r 'include "./tmp.php";'I get a stack trace instead of having the function 'exception_handler' called.& If run it like this:& & php tmp.phpIt works fine.& (Why run code from '-r'?& Sometimes it's useful to add stuff around the include like calls to microtime for benchmarks, or to include a library and then call a few functions from the library, all in an ad-hoc way without having to create new files.)PHP versions 5.1.2 and 5.0.4.
As of PHP 5.4.11....
Instead of:
Output: Fatal error: Exception thrown without a stack frame in Unknown on line 0
This snippet:
&?php
function error_handler($code, $message, $file, $line)
{
& & if (0 == error_reporting())
& & {
& & & &
& & }
& & throw new ErrorException($message, 0, $code, $file, $line);
}
function exception_handler($e)
{
& & print $undefined; }
set_error_handler("error_handler");
set_exception_handler("exception_handler");
throw new Exception("Just invoking the exception handler");
?&
Now returns:
Fatal error: Uncaught exception 'ErrorException' with message 'Undefined variable: undefined' in C:\Apache2\htdocs\error\test.php:13 Stack trace: #0 C:\Apache2\htdocs\error\test.php(13): error_handler(8, 'Undefined varia...', 'C:\Apache2\htdo...', 13, Array) #1 [internal function]: exception_handler(Object(Exception)) #2 {main} thrown in C:\Apache2\htdocs\error\test.php on line 13
So it appears that exceptions thrown within exception handler now bypass exception handler.
When an uncaught exception is handled, execution does NOT return to the script, but rather (unexpectedly, on my end anyway) terminates.I am using set_error_handler() and set_exception_handler() in conjunction for a system I am currently developing (on v5.3.0 with Xampp). Lets say two E_USER_NOTICES are triggered, the script will die after the first one is processed.&?php& & set_exception_handler( 'exc_handler' );& & function exc_handler($exception) {& & & & echo "Uncaught exception: " , $exception-&getMessage(), "\n";& & }& & function errorone() {& & & & throw new Exception("Test 1");& & }& & function errortwo() {& & & & throw new Exception("Test 2");& & }& & function test() {& & & & errorone();& & & & errortwo();& & }& & test();& & test();?&Instead of printing (as I'd expect) "Uncaught exception: Text 1\nUncaught exception: Text 2\nUncaught exception: Text 1\nUncaught exception: Text 2\n"It is only printed ONCE. I've tried a number of different things, but I can't figure out how to return execution to the script after the EXCEPTION HANDLER has run.If anyone has a solution on how to return execution (hence, allow the script to log uncaught exceptions but continue processing) then PLEASE email me! Thanks!
Hey all, i've just started to use the exception suite instead of the normal PHP error suite. For those of you looking for an object orientated way to do this without looking down at Glen and Sean's examples (Lesson 1: ALWAYS read the logs!), here you go:&?phpclass NewException extends Exception{& & public function __construct($message, $code=NULL)& & {& & & & parent::__construct($message, $code);& & }& & & & public function __toString()& & {& & & & return "Code: " . $this-&getCode() . "&br /&Message: " . htmlentities($this-&getMessage());& & }& & & & public function getException()& & {& & & & print $this; }& & & & public static function getStaticException($exception)& & {& & & && $exception-&getException(); }}set_exception_handler(array("NewException", "getStaticException"));throw new NewException("Catch me!!!", 69);?&Let me know if i'm missing something obvious as I left my glasses at home and I just came back from the Melbourne cup (If I won then I wouldn't be at work still!).
It seems that although the Exception contains a backtrace itself, the stack for the debug_backtrace() function is empty when entering an exception handler. This is very inconvinient. See bug #36477.
Using the 'set_exception_handler' function within a class, the defined 'exception_handler' method must be declared as 'public' (preferrable 'public static' if you use the "array('example', 'exception_handler')" syntax).
&?php
class example {
& & public function __construct() {
& & & & @set_exception_handler(array('example', 'exception_handler'));
& & & & throw new Exception('DOH!!');
& & }
& & public static function exception_handler($exception) {
& & & & print "Exception Caught: ". $exception-&getMessage() ."\n";
& & }
}
$example = new example;
echo "Not Executed\n";
?&
Declaring the 'exception_handler' function as 'private' causes a FATAL ERROR.
[derick: red. updated statement about static a bit]
In my experience, the static keyword is crucial for error handlers which are methods of a class instead of free-standing functions.& & static function exceptionHandler($exception)works but & & function exceptionHandler($exception)doesn't and results in a "Fatal error: Exception thrown without a stack frame in Unknown on line 0" message."public" is optional as it is the default anyway (but it is probably clearer to write it explicitly).

我要回帖

更多关于 runtimeexception 的文章

 

随机推荐