在上一篇文章中,我们介绍了20种常见的编译器错误,今天来探讨一下运行时异常以及导致这些异常的原因。接下来我们将聊聊30种常见的异常和错误,并且告诉你如何在代码中解决这些问题。 21.“ArrayIndexOutOfBoundsException”这是代码在尝试访问不在数组的索引取值范围内的元素时会显示的运行时错误消息。如下所示的代码会触发此异常: String[] name = { 'tom', 'dick', 'harry'};for (int i = 0; i <>'\n');} 如下是另外一个例子 : int[] list = new int[5];list[5] = 33; // illegal index, maximum index is 4 数组的索引是从零开始的,并且比数组长度小了1。通常,在定义数组索引的限制时,要使用“<><> 22.“StringIndexOutOfBoundsException” 当代码尝试访问字符串中不在字符串范围内的字符串片段时,就会出现此问题。这种情况通常会发生在代码尝试创建一个字符串的子字符串,可是传入的参数值不符合字符串长度限制的时候。如下就是这类问题的一个例子 : public class StringCharAtExample { public static void main(String[] args) { String str = 'Java Code Geeks!'; System.out.println('Length: ' + str.length()); //The following statement throws an exception, because //the request index is invalid. char ch = str.charAt(50); }} 像数组的索引一样,字符串的索引是从零开始的。索引字符串时,最后一个字符的索引值比字符串的长度小1。 “StringIndexOutOfBoundsException”这个错误消息一般都意味着索引正在尝试访问不存在于字符串中的字符。 23.“NullPointerException” 当程序尝试使用没有经过赋值的对象引用时,就会发生“NullPointerException”。 // A Java program to demonstrate that invoking a method// on null causes NullPointerExceptionimport java.io.*;class GFG{ public static void main (String[] args) { // Initializing String variable with null value String ptr = null; // Checking if ptr.equals null or works fine. try { // This line of code throws NullPointerException // because ptr is null if (ptr.equals('gfg')) System.out.print('Same'); else System.out.print('Not Same'); } catch(NullPointerException e) { System.out.print('NullPointerException Caught'); } }} Java 程序经常出现如下状况:
24.“NoClassDefFoundError” “NoClassDefFoundError”会发生在解释器找不到在主方法使用到了的类的文件的时候。 如果你对如下程序执行编译: class A{ // some code}public class B{ public static void main(String[] args) { A a = new A(); }} 它会生成两个 .class 文件:A.class 和 B.class。删除 A.class 文件并且运行 B.class 文件,就会得到 NoClassDefFoundError 错误消息: Exception in thread 'main' java.lang.NoClassDefFoundError: Aat MainClass.main(MainClass.java:10)Caused by: java.lang.ClassNotFoundException: Aat java.net.URLClassLoader.findClass(URLClassLoader.java:381)at java.lang.ClassLoader.loadClass(ClassLoader.java:424)at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)at java.lang.ClassLoader.loadClass(ClassLoader.java:357) 如果存在如下问题,就会发生这样的问题:
25.“NoSuchMethodFoundError” 当 Java 软件尝试调用类的方法而该方法在类里面没有定义时,就会出现这样的错误消息 : Error: Could not find or load main class wiki.java 当声明中有错别字的时候,一般就会出现“NoSuchMethodFoundError”这样的错误。 26. “NoSuchProviderException”当请求了一个不可用的安全方案提供方(Security Provider)的时候,就会引发“NoSuchProviderException” javax.mail.NoSuchProviderException 如果你在尝试找出“NoSuchProviderException”为什么会发生的原因,请进行如下检查:
27. AccessControlException AccessControlException 表示请求访问的系统资源(比如文件系统或这网络)被拒绝了,例如本例中的 JBossDeveloper : ERROR Could not register mbeans java.security.AccessControlException: WFSM000001: Permission check failed (permission '('javax.management.MBeanPermission' 'org.apache.logging.log4j.core.jmx.LoggerContextAdmin#-[org.apache.logging.log4j2:type=51634f]' 'registerMBean')' in code source '(vfs:/C:/wildfly-10.0.0.Final/standalone/deployments/mySampleSecurityApp.war/WEB-INF/lib/log4j-core-2.5.jar )' of 'null') 28. “ArrayStoreException”“ArrayStoreException”会发生在向 Java 的数组中转换元素受到转换规则限制而发生中断的时候。例如,这个来自于 JavaScan.com 的这个例子就表现了发生这种问题的程序 : /* ............... START ............... */ public class JavaArrayStoreException { public static void main(String...args) { Object[] val = new Integer[4]; val[0] = 5.8; } } /* ............... END ............... */ 输出结果如下: Exception in thread 'main' java.lang.ArrayStoreException: java.lang.Doubleat ExceptionHandling.JavaArrayStoreException.main(JavaArrayStoreException.java:7) 数组在被初始化的时候,需要声明允许进入数组的对象的种类。因此数组的每个元素都得是相同类型的对象。 29. “Bad Magic Number” 这个错误消息的意思是网络上的类定义文件可能出问题了。如下是服务器端的错误消息示例: Java(TM) Plug-in: Version 1.3.1_01Using JRE version 1.3.1_01 Java HotSpot(TM) Client VMUser home directory = C:\Documents and Settings\AnkurProxy Configuration: Manual ConfigurationProxy: 192.168.11.6:80java.lang.ClassFormatError: SalesCalculatorAppletBeanInfo (Bad magic number)at java.lang.ClassLoader.defineClass0(Native Method)at java.lang.ClassLoader.defineClass(Unknown Source)at java.security.SecureClassLoader.defineClass(Unknown Source)at sun.applet.AppletClassLoader.findClass(Unknown Source)at sun.plugin.security.PluginClassLoader.access$201(Unknown Source)at sun.plugin.security.PluginClassLoader$1.run(Unknown Source)at java.security.AccessController.doPrivileged(Native Method)at sun.plugin.security.PluginClassLoader.findClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)at sun.applet.AppletClassLoader.loadClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)at java.beans.Introspector.instantiate(Unknown Source)at java.beans.Introspector.findInformant(Unknown Source)at java.beans.Introspector.(Unknown Source)at java.beans.Introspector.getBeanInfo(Unknown Source)at sun.beans.ole.OleBeanInfo.(Unknown Source)at sun.beans.ole.StubInformation.getStub(Unknown Source)at sun.plugin.ocx.TypeLibManager$1.run(Unknown Source)at java.security.AccessController.doPrivileged(Native Method)at sun.plugin.ocx.TypeLibManager.getTypeLib(Unknown Source)at sun.plugin.ocx.TypeLibManager.getTypeLib(Unknown Source)at sun.plugin.ocx.ActiveXAppletViewer.statusNotification(Native Method)at sun.plugin.ocx.ActiveXAppletViewer.notifyStatus(Unknown Source)at sun.plugin.ocx.ActiveXAppletViewer.showAppletStatus(Unknown Source)at sun.applet.AppletPanel.run(Unknown Source)at java.lang.Thread.run(Unknown Source) “bad magic number”错误消息发生时,可能存在如下这些情况:
30. “Broken Pipe” 这样的错误消息表示来自于文件或网络套接字的数据流已停止工作或在另一端已经处于关闭状态 。 Exception in thread 'main' java.net.SocketException: Broken pipe at java.net.SocketOutputStream.socketWrite0(Native Method) at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92) at java.net.SocketOutputStream.write(SocketOutputStream.java:115) at java.io.DataOutputStream.write 数据管道中断发生的原因一般包括如下这些
31. “Could Not Create Java Virtual Machine”当 Java 代码尝试使用错误的参数来启动 Java 时,一般会产生这样的错误消息 : Error: Could not create the Java Virtual MachineError: A fatal exception has occurred. Program will exit. 它通常是由于代码中的声明中或者为其分配适当的内存时有错误而引起的。 32. “class file contains wrong class” “class file contains wrong class”问题一般会发生在 Java 代码尝试在错误的目录中寻找类文件的时候,产生类似于如下所示的错误消息: MyTest.java:10: cannot access MyStructbad class file: D:\Java\test\MyStruct.javafile does not contain class MyStructPlease remove or make sure it appears in the correct subdirectory of the classpath.MyStruct ms = new MyStruct();^ 要修复此问题,如下提示可以提供一些帮助:
33. “ClassCastException” “ClassCastException” 消息表示 Java 代码正尝试将对象转换到一个错误的类型。在下面这个来自于 Java 概念日有所进(Java Concept of the Day)的实例中, 运行着这样的程序: package com;class A{ int i = 10;}class B extends A{ int j = 20;}class C extends B{ int k = 30;}public class ClassCastExceptionDemo{ public static void main(String[] args) { A a = new B(); //B type is auto up casted to A type B b = (B) a; //A type is explicitly down casted to B type. C c = (C) b; //Here, you will get class cast exception System.out.println(c.k); }} 这会导致如下错误: Exception in thread “main” java.lang.ClassCastException: com.B cannot be cast to com.Cat com.ClassCastExceptionDemo.main(ClassCastExceptionDemo.java:23) Java 代码会创建一个类和子类的层级结构。为了避免 “ClassCastException” 错误,请确保新的类型归属于正确的类或者它的父类。如果使用了泛型的话,这些错误就可以在编译时被捕获到。 34. “ClassFormatError”“ClassFormatError” 消息指代的是一个链接错误,发生在一个类文件不能被读取或者解释为一个类文件的时候。 Caused by: java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/persistence/GenerationTypeat java.lang.ClassLoader.defineClass1(Native Method)at java.lang.ClassLoader.defineClassCond(Unknown Source)at java.lang.ClassLoader.defineClass(Unknown Source)at java.security.SecureClassLoader.defineClass(Unknown Source)at java.net.URLClassLoader.defineClass(Unknown Source)at java.net.URLClassLoader.access$000(Unknown Source)at java.net.URLClassLoader$1.run(Unknown Source)at java.security.AccessController.doPrivileged(Native Method)at java.net.URLClassLoader.findClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source) 关于“ClassFormatError”错误为什么会发生,有几种可能:
35. “ClassNotFoundException”“ClassNotFoundException” 只会发生于运行时——意味着本存在于编译时可是在运行时却丢失了。这是一个链接错误。 非常类似于 “NoClassDefFoundError”,如下情况就有可能让这样的问题发生:
36. “ExceptionInInitializerError”这个 Java 问题会在静态初始化有问题时发生 。当 Java 代码稍后要用到这个类时, 将会发生“NoClassDefFoundError” 错误. java.lang.ExceptionInInitializerError at org.eclipse.mat.hprof.HprofIndexBuilder.fill(HprofIndexBuilder.java:54) at org.eclipse.mat.parser.internal.SnapshotFactory.parse(SnapshotFactory.java:193) at org.eclipse.mat.parser.internal.SnapshotFactory.openSnapshot(SnapshotFactory.java:106) at com.squareup.leakcanary.HeapAnalyzer.openSnapshot(HeapAnalyzer.java:134) at com.squareup.leakcanary.HeapAnalyzer.checkForLeak(HeapAnalyzer.java:87) at com.squareup.leakcanary.internal.HeapAnalyzerService.onHandleIntent(HeapAnalyzerService.java:56) at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:145) at android.os.HandlerThread.run(HandlerThread.java:61)Caused by: java.lang.NullPointerException: in == null at java.util.Properties.load(Properties.java:246) at org.eclipse.mat.util.MessageUtil.(MessageUtil.java:28) at org.eclipse.mat.util.MessageUtil.(MessageUtil.java:13) ... 10 more 要修复此问题还需要更多的信息。在代码中使用 getCause() 可以返回导致被返回的错误发生的异常对象。 37. “IllegalBlockSizeException”“IllegalBlockSizeException” 会发生在解密时消息长度不是8位的倍数的时候。这里有一个来自于 ProgramCreek.com 的例子: @Overrideprotected byte[] engineWrap(Key key) throws IllegalBlockSizeException, InvalidKeyException { try { byte[] encoded = key.getEncoded(); return engineDoFinal(encoded, 0, encoded.length); } catch (BadPaddingException e) { IllegalBlockSizeException newE = new IllegalBlockSizeException(); newE.initCause(e); throw newE; }} “IllegalBlockSizeException” 可能由如下状况所导致:
38. “BadPaddingException”“BadPaddingException”会发生于解密时填充块被用来创建一个可以用 8 位的倍数来计算长度的消息的时候。这里有一个来自于 Stack Overflow 的例子: javax.crypto.BadPaddingException: Given final block not properly paddedat com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)at javax.crypto.Cipher.doFinal(DashoA13*..) 被加密的数据是二进制的,因此不要尝试着在一个字符串中去存储它,或者也有可能是加密期间数据没有进行恰当的填充。 39. “IncompatibleClassChangeError”“IncompatibleClassChangeError” 是链接错误 LinkageError 的一种形式,会在一个基类在其子类已经编译过了之后发生了概念时发生。这里有一个来自于 How to Do in Java 的例子 : Exception in thread 'main' java.lang.IncompatibleClassChangeError: Implementing classat java.lang.ClassLoader.defineClass1(Native Method)at java.lang.ClassLoader.defineClass(Unknown Source)at java.security.SecureClassLoader.defineClass(Unknown Source)at java.net.URLClassLoader.defineClass(Unknown Source)at java.net.URLClassLoader.access$000(Unknown Source)at java.net.URLClassLoader$1.run(Unknown Source)at java.security.AccessController.doPrivileged(Native Method)at java.net.URLClassLoader.findClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)at java.lang.ClassLoader.loadClassInternal(Unknown Source)at net.sf.cglib.core.DebuggingClassWriter.toByteArray(DebuggingClassWriter.java:73)at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:26)at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)at net.sf.cglib.core.KeyFactory$Generator.create(KeyFactory.java:144)at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:116)at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:108)at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:104)at net.sf.cglib.proxy.Enhancer.(Enhancer.java:69) 当 “IncompatibleClassChangeError” 发生时,有能发生了如下状况:
40. “FileNotFoundException” 这个 Java 软件错误消息会在指定路径名上的文件不存在是被抛出来。 @Override public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { if (uri.toString().startsWith(FILE_PROVIDER_PREFIX)) { int m = ParcelFileDescriptor.MODE_READ_ONLY; if (mode.equalsIgnoreCase('rw')) m = ParcelFileDescriptor.MODE_READ_WRITE; File f = new File(uri.getPath()); ParcelFileDescriptor pfd = ParcelFileDescriptor.open(f, m); return pfd; } else { throw new FileNotFoundException('Unsupported uri: ' + uri.toString()); }} 出来指定路径名上的文件不存在之外,这种问题也有可能意思是存在的文件是不可被访问的。 41. “EOFException”“EOFException”会在输出时不经意抵达了文件的终点或者流的终点时被抛出。这里有一个来自于 JavaBeat 的抛出了一个 EOFException 的应用程序示例: import java.io.DataInputStream;import java.io.EOFException;import java.io.File;import java.io.FileInputStream;import java.io.IOException;public class ExceptionExample { public void testMethod1() { File file = new File('test.txt'); DataInputStream dataInputStream = null; try { dataInputStream = new DataInputStream(new FileInputStream(file)); while (true) { dataInputStream.readInt(); } } catch (EOFException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (dataInputStream != null) { dataInputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { ExceptionExample instance1 = new ExceptionExample(); instance1.testMethod1(); }} 运行上述程序会导致如下异常: java.io.EOFExceptionat java.io.DataInputStream.readInt(DataInputStream.java:392)at logging.simple.ExceptionExample.testMethod1(ExceptionExample.java:16)at logging.simple.ExceptionExample.main(ExceptionExample.java:36) 当后面已经没有数据可供输出了,可 DataInputStream 仍在尝试读取流中的数据, “EOFException” 就会被抛出来。它也可以发生于 ObjectInputStream 和 RandomAccessFile 类的逻辑里面。 42. “UnsupportedEncodingException”该 Java 软件错误消息会在字符编码不被环境所支持的时候产生 。 public UnsupportedEncodingException() 所使用的 Java 虚拟机不支持某一种给定的字符集是有可能的。 43. “SocketException”“SocketException” 在创建或者访问套接字的时候有错误发生. public void init(String contextName, ContextFactory factory) { super.init(contextName, factory); String periodStr = getAttribute(PERIOD_PROPERTY); if (periodStr != null) { int period = 0; try { period = Integer.parseInt(periodStr); } catch (NumberFormatException nfe) {} if (period <>0) { throw new MetricsException('Invalid period: ' + periodStr); } setPeriod(period); } metricsServers = Util.parse(getAttribute(SERVERS_PROPERTY), DEFAULT_PORT); unitsTable = getAttributeTable(UNITS_PROPERTY); slopeTable = getAttributeTable(SLOPE_PROPERTY); tmaxTable = getAttributeTable(TMAX_PROPERTY); dmaxTable = getAttributeTable(DMAX_PROPERTY); try { datagramSocket = new DatagramSocket(); } catch (SocketException se) { se.printStackTrace(); }} 该异常一般会在最大连接数因为如下原因而满了的时候被抛出来:
44. “SSLException” 该 Java 软件错误消息会在有跟 SSL 相关的操作失败时发生。如下是一个来自于 Atlassian 的示例: com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty at com.sun.jersey.client.apache.ApacheHttpClientHandler.handle(ApacheHttpClientHandler.java:202) at com.sun.jersey.api.client.Client.handle(Client.java:365) at com.sun.jersey.api.client.WebResource.handle(WebResource.java:556) at com.sun.jersey.api.client.WebResource.get(WebResource.java:178) at com.atlassian.plugins.client.service.product.ProductServiceClientImpl.getProductVersionsAfterVersion(ProductServiceClientImpl.java:82) at com.atlassian.upm.pac.PacClientImpl.getProductUpgrades(PacClientImpl.java:111) at com.atlassian.upm.rest.resources.ProductUpgradesResource.get(ProductUpgradesResource.java:39) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at com.atlassian.plugins.rest.common.interceptor.impl.DispatchProviderHelper$ResponseOutInvoker$1.invoke(DispatchProviderHelper.java:206) at com.atlassian.plugins.rest.common.interceptor.impl.DispatchProviderHelper$1.intercept(DispatchProviderHelper.java:90) at com.atlassian.plugins.rest.common.interceptor.impl.DefaultMethodInvocation.invoke(DefaultMethodInvocation.java:61) at com.atlassian.plugins.rest.common.expand.interceptor.ExpandInterceptor.intercept(ExpandInterceptor.java:38) at com.atlassian.plugins.rest.common.interceptor.impl.DefaultMethodInvocation.invoke(DefaultMethodInvocation.java:61) at com.atlassian.plugins.rest.common.interceptor.impl.DispatchProviderHelper.invokeMethodWithInterceptors(DispatchProviderHelper.java:98) at com.atlassian.plugins.rest.common.interceptor.impl.DispatchProviderHelper.access$100(DispatchProviderHelper.java:28) at com.atlassian.plugins.rest.common.interceptor.impl.DispatchProviderHelper$ResponseOutInvoker._dispatch(DispatchProviderHelper.java:202) ...Caused by: javax.net.ssl.SSLException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty ...Caused by: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty ...Caused by: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty 如下情况有可能会导致这样的问题发生:
45. “MissingResourceException”“MissingResourceException” 会在某个资源丢失时发生。如果资源已经处于正确的类路径之下的话,那就一般是因为一个属性配置文件并没有被恰当的进行了配置。这里有一个示例 : java.util.MissingResourceException: Can't find bundle for base name localemsgs_en_US, locale en_USjava.util.ResourceBundle.throwMissingResourceExceptionjava.util.ResourceBundle.getBundleImpljava.util.ResourceBundle.getBundlenet.sf.jasperreports.engine.util.JRResourcesUtil.loadResourceBundlenet.sf.jasperreports.engine.util.JRResourcesUtil.loadResourceBundle 46. “NoInitialContextException”“NoInitialContextException”会在 Java 应用程序想要执行命名操作可是不能创建一个链接的时候发生. [java] Caused by: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial[java] at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)[java] at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:247)[java] at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:284)[java] at javax.naming.InitialContext.lookup(InitialContext.java:351)[java] at org.apache.camel.impl.JndiRegistry.lookup(JndiRegistry.java:51) 这会是一个解决起来比较复杂的问题,不过还是有一些可能的问题会导致 “NoInitialContextException” 错误消息的产生:
补充能量,回顾阅读: 一个十二年老程序猿的碎碎念 文章来源:互联网 |
|