Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException
вообще.
См. также: A хороший список лучших практик
Я бы добавил, очень важно, хорошо использовать модификатор final
. Использование "окончательной" модификатор, когда это применимо в Java
Сводка:
final
для обеспечения хорошей инициализации. @NotNull
и @Nullable
if("knownObject".equals(unknownObject)
valueOf()
поверх toString (). StringUtils
StringUtils.isEmpty(null)
. Рычаги завершения работы выполняются во всех случаях, где VM насильственно не уничтожается. Так, если необходимо было выпустить "стандартное" уничтожение (SIGTERM
от команды уничтожения) тогда, они выполнятся. Точно так же они выполнятся после вызова System.exit(int)
.
Однако твердое уничтожение (kill -9
или kill -SIGKILL
) тогда они не выполнятся. Так же (и очевидно) они не выполнятся, если Вы вытянете питание от компьютера, бросите его в чан кипящей лавы или победите ЦП в части с кувалдой. Вы, вероятно, уже знали это, все же.
Финализаторы действительно должны работать также, но лучше не полагаться на это для очистки завершения работы, а скорее полагаться на Ваши рычаги завершения работы для остановки вещей чисто. И, как всегда, быть осторожным с мертвыми блокировками (я видел, что слишком много рычагов завершения работы подвешивают весь процесс)!
Хорошо, после всех возможностей я принял решение работать с "Контролем Java и управлением"
, Обзор здесь
, Который позволяет Вам управлять одним приложением от другого относительно простым способом. Можно назвать приложение управления из сценария для остановки управляемого приложения корректно прежде, чем уничтожить его.
Вот упрощенный код:
Управляемое приложение:
выполняет его со следующими параметрами VM:
приложение Управления-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
//ThreadMonitorMBean.java
public interface ThreadMonitorMBean
{
String getName();
void start();
void stop();
boolean isRunning();
}
// ThreadMonitor.java
public class ThreadMonitor implements ThreadMonitorMBean
{
private Thread m_thrd = null;
public ThreadMonitor(Thread thrd)
{
m_thrd = thrd;
}
@Override
public String getName()
{
return "JMX Controlled App";
}
@Override
public void start()
{
// TODO: start application here
System.out.println("remote start called");
}
@Override
public void stop()
{
// TODO: stop application here
System.out.println("remote stop called");
m_thrd.interrupt();
}
public boolean isRunning()
{
return Thread.currentThread().isAlive();
}
public static void main(String[] args)
{
try
{
System.out.println("JMX started");
ThreadMonitorMBean monitor = new ThreadMonitor(Thread.currentThread());
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("com.example:type=ThreadMonitor");
server.registerMBean(monitor, name);
while(!Thread.interrupted())
{
// loop until interrupted
System.out.println(".");
try
{
Thread.sleep(1000);
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
// TODO: some final clean up could be here also
System.out.println("JMX stopped");
}
}
}
:
выполняет его с , остановка или запускается как параметр командной строки
public class ThreadMonitorConsole
{
public static void main(String[] args)
{
try
{
// connecting to JMX
System.out.println("Connect to JMX service.");
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
// Construct proxy for the the MBean object
ObjectName mbeanName = new ObjectName("com.example:type=ThreadMonitor");
ThreadMonitorMBean mbeanProxy = JMX.newMBeanProxy(mbsc, mbeanName, ThreadMonitorMBean.class, true);
System.out.println("Connected to: "+mbeanProxy.getName()+", the app is "+(mbeanProxy.isRunning() ? "" : "not ")+"running");
// parse command line arguments
if(args[0].equalsIgnoreCase("start"))
{
System.out.println("Invoke \"start\" method");
mbeanProxy.start();
}
else if(args[0].equalsIgnoreCase("stop"))
{
System.out.println("Invoke \"stop\" method");
mbeanProxy.stop();
}
// clean up and exit
jmxc.close();
System.out.println("Done.");
}
catch(Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Вот именно.:-)
Подобный Вопрос Здесь
Финализаторы в Java плох. Они добавляют много издержек к сборке "мусора". Избегайте их, когда это возможно.
shutdownHook только назовут, когда VM закроется. Я думаю, что это очень хорошо может сделать то, что Вы хотите.
Передача сигналов в Linux может быть сделана с "уничтожением" (человек уничтожают для доступных сигналов), Вам был бы нужен идентификатор процесса, чтобы сделать это. (топор PS | grep Java) или что-то как этот или хранилище идентификатор процесса, когда процесс создается (это используется в большинстве файлов запуска Linux, видит/etc/init.d)
, Портативная передача сигналов может быть сделана путем интеграции SocketServer в JAVA-приложении. Дело не в этом трудный и дает Вам свободу отправить любую команду, которую Вы хотите.
, Если Вы имели в виду наконец пункты в земельном участке финализаторов; они не получают extecuted, когда System.exit () называют. Финализаторы должны работать, но не должны действительно делать ничего более значительного, но печатать оператор отладки. Они опасны.
Спасибо за Вас ответы. Завершение работы сцепляет швы как что-то, что работало бы в моем случае. Но я также врезался в названный Контроль вещи и бобы управления:
http://java.sun.com/j2se/1.5.0/docs/guide/management/overview.html
, Который дает некоторые хорошие возможности для дистанционного мониторинга и управления процессом Java. (Был представлен в Java 5)
Другой способ: ваше приложение может открыть серверный сокет и ждать, пока на него поступит информация. Например, строка с «волшебным» словом :), а затем реакция на завершение работы: System.exit (). Вы можете отправить такую информацию в socke с помощью внешнего приложения, такого как telnet.