接上文50个常见的 Java 错误及避免方法(第二部分)
当我们尝试调用带有错误参数的Java代码时,通常会产生此Java错误消息(@ghacksnews):
Error: Could not createthe Java VirtualMachine
Error: A fatal exceptionhas occurred. Program will exit.
这通常是由于代码中的声明存在错误或为其分配适当的内存而引起的。
当Java代码尝试在错误的目录中寻找类文件时,就会出现“class file contains wrong class”的问题,导致类似于以下内容的错误消息:
MyTest.java:10: cannot access MyStruct
bad class file: D:\Java\test\MyStruct.java
file does notcontain class MyStruct
Please remove ormake sure it appears in the correctsubdirectory of the classpath.
MyStruct ms = new MyStruct();
要修复此错误,以下这些提示可以提供帮助:
确保源文件的名称和类的名称匹配——包括大小写。
检查软件包语句是否正确或是否缺失。
确保源文件位于正确的目录中。
“ClassCastException”消息指示了Java代码正在尝试将对象转换为错误的类。在来自Java Concept of 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
{
publicstatic voidmain(String[] args)
{
A a = new B(); //B type is auto up casted to A type
B b =(B) a; //Atype 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 cannotbe castto com.C
at com.ClassCastExceptionDemo.main(ClassCastExceptionDemo.java:23)
Java代码将创建一个类和子类的层次结构。为了避免“ClassCastException”错误,请确保新类型属于正确的类或其父类之一。如果使用泛型,则编译代码时可能会捕获这些错误。
“ClassFormatError”消息指示链接错误,并且发生在类文件不能被读取或解释为类文件的时候。
Caused by:java.lang.ClassFormatError: Absent Codeattribute in method that is not native orabstract in class filejavax/persistence/GenerationType
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(UnknownSource)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(UnknownSource)
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(NativeMethod)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(UnknownSource)
at java.lang.ClassLoader.loadClass(UnknownSource)
有若干原因会导致“ClassFormatError”错误:
类文件以ASCII模式而不是二进制模式上传。
Web服务器必须以二进制而不是ASCII格式发送类文件。
可能会有一个类路径错误,阻止了代码找到类文件。
如果类被加载两次,那么第二次将导致抛出异常。
正在使用旧版本的Java运行时。
“ClassNotFoundException”仅在运行时发生——意味着在编译期间有一个类在运行时缺失了。这是一个链接错误。
很像“NoClassDefFoundError”,在以下情况下会出现这个问题:
该文件不在正确的目录中。
类的名称必须与文件的名称相同(不包括文件扩展名)。 名称区分大小写。
此Java问题发生在静态初始化出错的时候(@GitHub)。 当Java代码稍后使用该类时,将发生“NoClassDefFoundError”错误。
java.lang.ExceptionInInitializerError
atorg.eclipse.mat.hprof.HprofIndexBuilder.fill(HprofIndexBuilder.java:54)
atorg.eclipse.mat.parser.internal.SnapshotFactory.parse(SnapshotFactory.java:193)
atorg.eclipse.mat.parser.internal.SnapshotFactory.openSnapshot(SnapshotFactory.java:106)
atcom.squareup.leakcanary.HeapAnalyzer.openSnapshot(HeapAnalyzer.java:134)
atcom.squareup.leakcanary.HeapAnalyzer.checkForLeak(HeapAnalyzer.java:87)
atcom.squareup.leakcanary.internal.HeapAnalyzerService.onHandleIntent(HeapAnalyzerService.java:56)
atandroid.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
atandroid.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)
atorg.eclipse.mat.util.MessageUtil.(MessageUtil.java:28)
at org.eclipse.mat.util.MessageUtil.(MessageUtil.java:13)
... 10 more
修复此错误我们需要更多的信息。在代码中使用getCause()可以返回导致错误的异常。
当长度消息不是8字节的倍数时,那么在解密期间就会抛出“IllegalBlockSizeException”异常。以下是一个出自ProgramCreek.com的示例(@ProgramCreek):
@Override
protected byte[]engineWrap(Key key) throwsIllegalBlockSizeException, InvalidKeyException {
try {
byte[] encoded = key.getEncoded();
return engineDoFinal(encoded, 0, encoded.length);
} catch (BadPaddingException e) {
IllegalBlockSizeException newE = newIllegalBlockSizeException();
newE.initCause(e);
throw newE;
}
}
“IllegalBlockSizeException”可能是由以下原因引起的:
使用不同的加密和解密算法选项。
要解密的消息可能在传输中被截断或乱码。
当使用填充来创建一个消息而不是8字节的倍数时,那么在解密期间可能会出现“BadPaddingException”异常。这是出自Stack Overflow的一个例子(@StackOverflow):
javax.crypto.BadPaddingException: Givenfinal blocknot properlypadded
at 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*..)
加密数据是二进制的,所以不要尝试将其存储在字符串或在加密期间没有被正确填充的数据中。
“IncompatibleClassChangeError”是LinkageError的一种形式,如果一个在基类在编译子类之后发生变化,那么就会出现此异常。下面这个例子来自于How to Do in Java(@HowToDoInJava):
Exception inthread "main" java.lang.IncompatibleClassChangeError: Implementing class
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(UnknownSource)
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(NativeMethod)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(UnknownSource)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(UnknownSource)
atnet.sf.cglib.core.DebuggingClassWriter.toByteArray(DebuggingClassWriter.java:73)
atnet.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:26)
atnet.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
atnet.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)
atnet.sf.cglib.proxy.Enhancer.(Enhancer.java:69)
出现“IncompatibleClassChangeError”有可能的原因是:
忘记了主方法的静态。
非法使用了legal类。
类被改变了,并且存在通过旧的签名从另一个类到这个类的引用。尝试删除所有类文件并重新编译所有内容。
40.“FileNotFoundException”
当具有指定路径名的文件不存在时,将抛出此Java软件错误消息。
@Override publicParcelFileDescriptor openFile(Uriuri, String mode) throwsFileNotFoundException {
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 newFileNotFoundException("Unsupported uri: "+ uri.toString());
}
}
除了没有指定路径名的文件之外,这可能意味着现有文件无法访问。
当输入期间意外终止文件或流时,将抛出“EOFException”。 以下是抛出EOFException异常的一个示例,来自JavaBeat应用程序:
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class ExceptionExample {
public voidtestMethod1() {
File file = newFile("test.txt");
DataInputStream dataInputStream = null;
try {
dataInputStream = newDataInputStream(newFileInputStream(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 staticvoid main(String[]args) {
ExceptionExample instance1 = newExceptionExample();
instance1.testMethod1();
}
}
运行上面的程序,将抛出以下异常:
java.io.EOFException
at 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类中。
当不支持字符编码时,会抛出此Java软件错误消息(@Penn)。
public UnsupportedEncodingException()
正在使用的Java虚拟机可能不支持给定的字符集。
“SocketException”异常表示创建或访问套接字时出错(@ProgramCreek)。
public void init(String contextName, ContextFactoryfactory) {
super.init(contextName, factory);
StringperiodStr = getAttribute(PERIOD_PROPERTY);
if (periodStr != null){
int period = 0;
try {
period = Integer.parseInt(periodStr);
} catch (NumberFormatException nfe) {}
if (period <= 0){
throw newMetricsException("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 = newDatagramSocket();
} catch (SocketException se) {
se.printStackTrace();
}
}
当由于以下原因而达到最大连接时,通常会抛出此异常:
没有更多的网络端口可用于应用程序。
系统没有足够的内存来支持新的连接。
44.“SSLException”
此Java软件错误消息发生在与SSL相关的操作出现故障的时候。 以下示例来自Atlassian(@Atlassian):
com.sun.jersey.api.client.ClientHandlerException:javax.net.ssl.SSLException:java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: thetrustAnchors parameter must be non-empty
atcom.sun.jersey.client.apache.ApacheHttpClientHandler.handle(ApacheHttpClientHandler.java:202)
at com.sun.jersey.api.client.Client.handle(Client.java:365)
atcom.sun.jersey.api.client.WebResource.handle(WebResource.java:556)
atcom.sun.jersey.api.client.WebResource.get(WebResource.java:178)
atcom.atlassian.plugins.client.service.product.ProductServiceClientImpl.getProductVersionsAfterVersion(ProductServiceClientImpl.java:82)
atcom.atlassian.upm.pac.PacClientImpl.getProductUpgrades(PacClientImpl.java:111)
atcom.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)
atcom.atlassian.plugins.rest.common.interceptor.impl.DispatchProviderHelper$ResponseOutInvoker$1.invoke(DispatchProviderHelper.java:206)
atcom.atlassian.plugins.rest.common.interceptor.impl.DispatchProviderHelper$1.intercept(DispatchProviderHelper.java:90)
atcom.atlassian.plugins.rest.common.interceptor.impl.DefaultMethodInvocation.invoke(DefaultMethodInvocation.java:61)
atcom.atlassian.plugins.rest.common.expand.interceptor.ExpandInterceptor.intercept(ExpandInterceptor.java:38)
atcom.atlassian.plugins.rest.common.interceptor.impl.DefaultMethodInvocation.invoke(DefaultMethodInvocation.java:61)
atcom.atlassian.plugins.rest.common.interceptor.impl.DispatchProviderHelper.invokeMethodWithInterceptors(DispatchProviderHelper.java:98)
atcom.atlassian.plugins.rest.common.interceptor.impl.DispatchProviderHelper.access$100(DispatchProviderHelper.java:28)
atcom.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: thetrustAnchors parameter must be non-empty
...
Caused by: java.lang.RuntimeException:Unexpected error: java.security.InvalidAlgorithmParameterException: thetrustAnchors parameter must be non-empty
...
Caused by: java.security.InvalidAlgorithmParameterException:the trustAnchors parameter must be non-empty
发生这种情况的原因有:
· 服务器或客户端上的证书已过期。
· 服务器端口已重置为另一个端口。
45.“MissingResourceException”
当资源丢失时,会发生“MissingResourceException”异常。如果资源在正确的类路径中,那么通常是因为属性文件没有正确配置。下面有一个例子(@TIBCO):
java.util.MissingResourceException:Can't findbundle for base namelocalemsgs_en_US, locale en_US
java.util.ResourceBundle.throwMissingResourceException
java.util.ResourceBundle.getBundleImpl
java.util.ResourceBundle.getBundle
net.sf.jasperreports.engine.util.JRResourcesUtil.loadResourceBundle
net.sf.jasperreports.engine.util.JRResourcesUtil.loadResourceBundle
46.“NoInitialContextException”
当Java应用程序想要执行命名操作但无法创建连接时,会发生“NoInitialContextException”异常(@TheASF)。
[java] Causedby: javax.naming.NoInitialContextException:Need tospecify classname inenvironment or systemproperty, oras anapplet parameter,or inan applicationresource 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”Java错误消息的原因:
· 应用程序可能没有正确的凭据进行连接。
· 代码可能无法识别所需的JNDI实现。
· InitialContext类可能没有配置正确的属性。
47.“NoSuchElementException”
当迭代(例如“for”循环)尝试访问下一个元素而没有元素的时候,就会出现“NoSuchElementException”异常。
public class NoSuchElementExceptionDemo{
public staticvoid main(Stringargs[]) {
Hashtable sampleMap = newHashtable();
Enumeration enumeration = sampleMap.elements();
enumeration.nextElement(); //java.util.NoSuchElementExcepiton here becauseenumeration is empty
}
}
Output:
Exception inthread "main"java.util.NoSuchElementException: Hashtable Enumerator
atjava.util.Hashtable$EmptyEnumerator.nextElement(Hashtable.java:1084)
attest.ExceptionTest.main(NoSuchElementExceptionDemo.java:23)
抛出“NoSuchElementException”可能的途径:
· Enumeration::nextElement()
· NamingEnumeration::next()
· StringTokenizer::nextElement()
· Iterator::next()
48.“NoSuchFieldError”
当应用程序尝试访问对象中的一个字段,但指定的字段不再存在于对象中时,将抛出此Java软件错误消息(@sourceforge)。
public NoSuchFieldError()
通常,该错误在编译器中被捕获,但是如果在编译和运行之间更改了类定义,则在运行时将被捕获。
49.“NumberFormatException”
当应用程序尝试将字符串转换为数字类型,但该数字不是有效的数字字符串时,会出现此Java软件错误消息(@alvinalexander)。
package com.devdaily.javasamples;
public class ConvertStringToNumber {
public staticvoid main(String[]args) {
try {
String s = "FOOBAR";
int i = Integer.parseInt(s);
// this line of code will never be reached
System.out.println("int value = "+ i);
}
catch (NumberFormatException nfe) {
nfe.printStackTrace();
}
}
}
可能抛出“NumberFormatException”的原因有:
· 数字中的前导或尾随空格。
· 标志不在数字前面。
· 数字有逗号。
· 本地化可能不会将其分类为有效数字。
· 数字太大,不适合数字类型。
50.“TimeoutException”
当阻塞操作超时时,会出现此Java软件错误消息。
private void queueObject(ComplexDataObject obj) throws TimeoutException, InterruptedException {
if (!queue.offer(obj, 10,TimeUnit.SECONDS)) {
TimeoutException ex = newTimeoutException("Timed out waiting for parsedelements to be processed. Aborting.");
throw ex;
}
}
到这里就全部完结了! 如果你细细阅读了整篇文章,那么相信现在你应该能处理各种运行时和编译器的错误和异常了。编程愉快!