Java: таинственный обработчик исключений неперехваченного Java [с кодом]
Произошло что-то странное. Я написал программу на Java, в которой ничего не сделал для обработки необработанных исключений каким-либо особым образом. Но когда я запускаю эту конкретную программу в Windows 7, в статическом контексте, вызываемом из main, возникает это необработанное исключение, которое вызывает всплывающее окно с отображением исключения. Я пытался написать небольшую программу, чтобы дублировать этот эффект безрезультатно. Одна программа (которую я написал полностью вручную) создает всплывающее окно, в то время как другие не будут делать то же самое.
Я хотел бы отследить это особенно, чтобы я мог добавить код, который заставляет другие исключения CAUGHT отображать трассировку стека подобным образом.
Я спрашивал об этом в IRC, но люди говорят мне, что этого не происходит. Ну, это случилось. Скриншот ниже.
Я думаю, что моя единственная надежда, если кто-то еще признает это и может сказать мне, откуда это происходит.
Спасибо!
ОБНОВЛЕНИЕ: Извините за задержку получения некоторого кода. Я должен был позаботиться о колики младенца. Обратите внимание, что это настольное Java-приложение. Это не апплет, и он не использует веб-запуск.
Вот код, скопированный и вставленный из программы, которая получает диалог. Я сделаю еще одно редактирование, чтобы вы знали, получает ли мой коллега (который получает исключение) диалог по этому делу. Я был осторожен, чтобы включить все, что привело к исключению. Отсутствует только реализация класса IPAddress, но она не участвует в исключении, поскольку фактически не используется до тех пор, пока не произойдет исключение. Обратите внимание на звездочки перед строкой, где происходит исключение. Эта строка кода соответствует исключению, которое вы видите на скриншоте.
package staticexception;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import javax.swing.UIManager;
public class StaticException {
// Don't need this fully implemented.
public static class IPAddress {
public static IPAddress getBroadcast(IPAddress mask, IPAddress myip) {
return new IPAddress();
}
public IPAddress() {}
public IPAddress(int maskval) {}
public IPAddress(byte[] addr) {}
public IPAddress mask(IPAddress netmask) {
return this;
}
public int prefixLength() {
return 0;
}
}
public static class Network {
public IPAddress broadcast, netmask, ip;
boolean remember;
public Network(IPAddress br, IPAddress nm, IPAddress ip) {
broadcast = br;
netmask = nm;
this.ip = ip;
}
boolean match(IPAddress ip) {
IPAddress a = ip.mask(netmask);
IPAddress b = this.ip.mask(netmask);
return (a.equals(b));
}
@Override
public String toString() {
return ip.toString() + "/" + netmask.prefixLength();
}
}
static List<Network> my_networks;
static void enumerateNetworks() {
my_networks = new ArrayList<Network>();
Enumeration<NetworkInterface> nets = null;
try {
nets = NetworkInterface.getNetworkInterfaces();
} catch (SocketException ex) {
ex.printStackTrace();
}
for (NetworkInterface netint : Collections.list(nets)) {
for (InterfaceAddress address : netint.getInterfaceAddresses()) {
// *** Exception would occur on the next line when
// *** address.getAddress() would return null
byte[] addr = address.getAddress().getAddress();
if (addr.length == 4 && addr[0] != 127) {
int prefixlen = address.getNetworkPrefixLength();
int maskval = -1 << (32 - prefixlen);
IPAddress mask = new IPAddress(maskval);
//my_netmask = mask;
System.out.println("Netmask = " + mask);
IPAddress myip = new IPAddress(addr);
//my_ip_address = myip;
System.out.println("Local IP = " + myip);
IPAddress broadcast = IPAddress.getBroadcast(mask, myip);
System.out.println("Broadcast = " + broadcast);
my_networks.add(new Network(broadcast, mask, myip));
System.out.print(address.getAddress().getAddress().length + " ");
System.out.print(address.getAddress() + " ");
System.out.print(address.getAddress().getHostAddress() + " ");
System.out.println(address.getNetworkPrefixLength());
}
}
}
}
static private void setupNetwork() {
System.setProperty("java.net.preferIPv4Stack","true");
enumerateNetworks();
// ... stuff that would happen after the exception
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {}
setupNetwork();
// ... stuff that would happen after the exception
}
}
ВТОРОЕ ОБНОВЛЕНИЕ: мой коллега сообщает, что эта программа НЕ создает диалоговое окно. Единственная разница между этим и программой, которая получает всплывающее окно, состоит в том, что программа, которая получает всплывающее окно, запускается из оболочки exe, созданной AdvancedInstaller. Кроме того, в Java-программе последовательность выполнения идентична. Я гуглил это, и насколько я могу найти, AdvancedInstaller не делает ничего, что могло бы привести к созданию этого всплывающего окна. Я не уверен, что это МОЖЕТ без изменения Java-программы (чего не происходит), потому что я не уверен, что вы можете сделать что-нибудь из-за пределов Java-программы, чтобы это произошло. За исключением, возможно, захвата stderr, но это не объясняет, почему другие программы, упакованные AdvancedInstaller, не создают это всплывающее окно или почему более поздние исключения, создаваемые этим приложением, также не создают это всплывающее окно.
1 ответ
2-й ответ (после добавления дополнительной информации к вопросу)
У расширенного установщика есть параметр "Проверка при запуске", описанный ниже:
Проверка при запуске
Любое неперехваченное исключение из основного потока описывается в диалоговом окне, которое позволит пользователю либо остановить приложение, либо проигнорировать исключение. Эта опция применяется только к приложениям с графическим интерфейсом.
Дополнительная информация: http://www.advancedinstaller.com/user-guide/java-product-settings.html.
1-й ответ
Это сильно зависит от контекста, и вы не предоставили достаточно информации, чтобы получить очень конкретный ответ. Loc2.LoC2.java, скорее всего, пользовательский или специфичный для проекта код.
Однако, как правило, необработанным обработчиком можно управлять (или запрашивать) с помощью:
Thread.setDefaultUncaughtExceptionHandler
а такжеThread.getDefaultUncaughtExceptionHandler
Больше информации: