50個常見的 Java 錯誤及避免方法(第三部分)

2017-09-23    分類:JAVA開發、程式設計開發、首頁精華0人評論發表於2017-09-23

本文由碼農網 – 小峰原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃

接上文50個常見的 Java 錯誤及避免方法(第二部分)

31.“Could Not Create Java Virtual Machine”

當我們嘗試呼叫帶有錯誤引數的Java程式碼時,通常會產生此Java錯誤訊息(@ghacksnews):

Error: Could not create the Java Virtual Machine
Error: A fatal exception has occurred. Program will exit.

這通常是由於程式碼中的宣告存在錯誤或為其分配適當的記憶體而引起的。

閱讀關於如何修復Java軟體錯誤“Could Not Create Java Virtual Machine”的討論。(@StackOverflow)

32.“class file contains wrong class”

當Java程式碼嘗試在錯誤的目錄中尋找類檔案時,就會出現“class file contains wrong class”的問題,導致類似於以下內容的錯誤訊息:

MyTest.java:10: cannot access MyStruct 
bad class file: D:\Java\test\MyStruct.java 
file does not contain class MyStruct 
Please remove or make sure it appears in the correct subdirectory of the classpath. 
MyStruct ms = new MyStruct();

要修復此錯誤,以下這些提示可以提供幫助:

  • 確保原始檔的名稱和類的名稱匹配——包括大小寫。
  • 檢查軟體包語句是否正確或是否缺失。
  • 確保原始檔位於正確的目錄中。

閱讀此關於如何修復“class file contains wrong class”錯誤的討論。(@StackOverflow)

33.“ClassCastException”

“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
{
    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.C
at com.ClassCastExceptionDemo.main(ClassCastExceptionDemo.java:23)

Java程式碼將建立一個類和子類的層次結構。為了避免“ClassCastException”錯誤,請確保新型別屬於正確的類或其父類之一。如果使用泛型,則編譯程式碼時可能會捕獲這些錯誤。

閱讀此教程以瞭解如何修復“ClassCastException”的Java軟體錯誤。(@java_concept)

34.“ClassFormatError”

“ClassFormatError”訊息指示連結錯誤,並且發生在類檔案不能被讀取或解釋為類檔案的時候。

Caused by: java.lang.ClassFormatError: Absent Code attribute in method that is
        not native or abstract in class file javax/persistence/GenerationType
at 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”錯誤:

  • 類檔案以ASCII模式而不是二進位制模式上傳。
  • Web伺服器必須以二進位制而不是ASCII格式傳送類檔案。
  • 可能會有一個類路徑錯誤,阻止了程式碼找到類檔案。
  • 如果類被載入兩次,那麼第二次將導致丟擲異常。
  • 正在使用舊版本的Java執行時。

閱讀此關於導致Java“ClassFormatError”錯誤的原因的討論。(@StackOverflow)

35.“ClassNotFoundException”

“ClassNotFoundException”僅在執行時發生——意味著在編譯期間有一個類在執行時缺失了。這是一個連結錯誤。

很像“NoClassDefFoundError”,在以下情況下會出現這個問題:

  • 該檔案不在正確的目錄中。
  • 類的名稱必須與檔案的名稱相同(不包括副檔名)。 名稱區分大小寫。

閱讀此關於導致“ClassNotFoundException”原因的更多案例的討論。(@StackOverflow)。

36.“ExceptionInInitializerError”

此Java問題發生在靜態初始化出錯的時候(@GitHub)。 當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()可以返回導致錯誤的異常。

閱讀此關於如何追蹤ExceptionInInitializerError原因的討論。(@StackOverflow)

37.“IllegalBlockSizeException”

當長度訊息不是8位元組的倍數時,那麼在解密期間就會丟擲“IllegalBlockSizeException”異常。以下是一個出自ProgramCreek.com的示例(@ProgramCreek):

@Override
protected 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”可能是由以下原因引起的:

  • 使用不同的加密和解密演算法選項。
  • 要解密的訊息可能在傳輸中被截斷或亂碼。

閱讀關於如何防止IllegalBlockSizeException Java軟體錯誤訊息的討論。(@StackOverflow)

38.“BadPaddingException”

當使用填充來建立一個訊息而不是8位元組的倍數時,那麼在解密期間可能會出現“BadPaddingException”異常。這是出自Stack Overflow的一個例子(@StackOverflow):

javax.crypto.BadPaddingException: Given final block not properly padded
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*..)

加密資料是二進位制的,所以不要嘗試將其儲存在字串或在加密期間沒有被正確填充的資料中。

閱讀關於如何防止BadPaddingException的討論。(@StackOverflow)

39.“IncompatibleClassChangeError”

“IncompatibleClassChangeError”是LinkageError的一種形式,如果一個在基類在編譯子類之後發生變化,那麼就會出現此異常。下面這個例子來自於How to Do in Java(@HowToDoInJava):

Exception in thread "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(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”有可能的原因是:

  • 忘記了主方法的靜態。
  • 非法使用了legal類。
  • 類被改變了,並且存在通過舊的簽名從另一個類到這個類的引用。嘗試刪除所有類檔案並重新編譯所有內容。

嘗試解決“IncompatibleClassChangeError”的這些步驟(@javacodegeeks)

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());
    }
}

除了沒有指定路徑名的檔案之外,這可能意味著現有檔案無法訪問。

閱讀關於為什麼會丟擲“FileNotFoundException”的討論。(@StackOverflow)

41.“EOFException”

當輸入期間意外終止檔案或流時,將丟擲“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 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.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軟體時可能發生“EOFException”的討論。(@StackOverflow)

42.“UnsupportedEncodingException”

當不支援字元編碼時,會丟擲此Java軟體錯誤訊息(@Penn)。

public UnsupportedEncodingException()

正在使用的Java虛擬機器可能不支援給定的字符集。

閱讀關於如何在執行Java軟體時處理“UnsupportedEncodingException”異常的討論。(@StackOverflow)

43.“SocketException”

“SocketException”異常表示建立或訪問套接字時出錯(@ProgramCreek)。

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();
    }
}

當由於以下原因而達到最大連線時,通常會丟擲此異常:

  • 沒有更多的網路埠可用於應用程式。
  • 系統沒有足夠的記憶體來支援新的連線。

閱讀關於如何在執行Java軟體時解決“SocketException”問題的討論。(@StackOverflow)

44.“SSLException”

此Java軟體錯誤訊息發生在與SSL相關的操作出現故障的時候。 以下示例來自Atlassian(@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

發生這種情況的原因有:

  • 伺服器或客戶端上的證照已過期。
  • 伺服器埠已重置為另一個埠。

閱讀關於可能導致Java軟體“SSLException”錯誤的討論。(@StackOverflow)

45.“MissingResourceException”

當資源丟失時,會發生“MissingResourceException”異常。如果資源在正確的類路徑中,那麼通常是因為屬性檔案沒有正確配置。下面有一個例子(@TIBCO):

java.util.MissingResourceException: Can't find bundle for base name localemsgs_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

閱讀關於如何在執行Java軟體時修復“MissingResourceException”的討論

46.“NoInitialContextException”

當Java應用程式想要執行命名操作但無法建立連線時,會發生“NoInitialContextException”異常(@TheASF)。

[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”Java錯誤訊息的原因:

  • 應用程式可能沒有正確的憑據進行連線。
  • 程式碼可能無法識別所需的JNDI實現。
  • InitialContext類可能沒有配置正確的屬性。

閱讀關於執行Java軟體時“NoInitialContextException”意味什麼的討論。(@StackOverflow)

47.“NoSuchElementException”

當迭代(例如“for”迴圈)嘗試訪問下一個元素而沒有元素的時候,就會出現“NoSuchElementException”異常。

public class NoSuchElementExceptionDemo{
    public static void main(String args[]) {
        Hashtable sampleMap = new Hashtable();
        Enumeration enumeration = sampleMap.elements();
        enumeration.nextElement();  //java.util.NoSuchElementExcepiton here because enumeration is empty
    }
}
Output:
Exception in thread "main" java.util.NoSuchElementException: Hashtable Enumerator
        at java.util.Hashtable$EmptyEnumerator.nextElement(Hashtable.java:1084)
        at test.ExceptionTest.main(NoSuchElementExceptionDemo.java:23)

丟擲“NoSuchElementException”可能的途徑:

  • Enumeration:: nextElement()
  • NamingEnumeration::next()
  • StringTokenizer:: nextElement()
  • Iterator::next()

閱讀此關於如何在Java軟體中修復“NoSuchElementException”的教程。(@javinpaul)

48.“NoSuchFieldError”

當應用程式嘗試訪問物件中的一個欄位,但指定的欄位不再存在於物件中時,將丟擲此Java軟體錯誤訊息(@sourceforge)。

public NoSuchFieldError()

通常,該錯誤在編譯器中被捕獲,但是如果在編譯和執行之間更改了類定義,則在執行時將被捕獲。

閱讀此關於如何在執行Java軟體時發現什麼導致“NoSuchFieldError”的討論。(@StackOverflow)

49.“NumberFormatException”

當應用程式嘗試將字串轉換為數字型別,但該數字不是有效的數字字串時,會出現此Java軟體錯誤訊息(@alvinalexander)。

package com.devdaily.javasamples;
public class ConvertStringToNumber {
    public static void 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”的原因有:

  • 數字中的前導或尾隨空格。
  • 標誌不在數字前面。
  • 數字有逗號。
  • 本地化可能不會將其分類為有效數字。
  • 數字太大,不適合數字型別。

閱讀關於如何在執行Java軟體時避免“NumberFormatException”的討論。(@StackOverflow)。

50.“TimeoutException”

當阻塞操作超時時,會出現此Java軟體錯誤訊息。

private void queueObject(ComplexDataObject obj) throws TimeoutException, InterruptedException {
    if (!queue.offer(obj, 10, TimeUnit.SECONDS)) {
        TimeoutException ex = new TimeoutException("Timed out waiting for parsed elements to be processed. Aborting.");
        throw ex;
    }
}

閱讀此關於如何在執行Java軟體時處理“TimeoutException”的討論。(@StackOverflow)。

結論

到這裡就全部完結了! 如果你細細閱讀了整篇文章,那麼相信現在你應該能處理各種執行時和編譯器的錯誤和異常了。程式設計愉快!

前面兩篇連結:

50個常見的 Java 錯誤及避免方法(第一部分)

50個常見的 Java 錯誤及避免方法(第二部分)

譯文連結:http://www.codeceo.com/article/50-java-errors-part-3.html
英文原文:50 Common Java Errors and How to Avoid Them (Part 2)
翻譯作者:碼農網 – 小峰
轉載必須在正文中標註並保留原文連結、譯文連結和譯者等資訊。]

相關文章