Hãy xem xét các lỗi thời gian chạy Java

Feb 26 2023
Tổng quan nhanh về Lỗi thời gian chạy Java · Lỗi thời gian chạy trong Java là gì? · Lỗi thời gian chạy VS Lỗi thời gian biên dịch · Các loại lỗi thời gian chạy · Lỗi thời gian chạy xuất hiện như thế nào? · Tôi có cần ném Lỗi thời gian chạy · Điều gì xảy ra khi bạn không' không bắt được ngoại lệ thời gian chạy · Ví dụ về lỗi thời gian chạy Lỗi thời gian chạy trong Java là gì? Các lỗi xảy ra tại thời điểm thực hiện chương trình được gọi là lỗi thời gian chạy. Những loại lỗi này không thể được phát hiện tại thời điểm biên dịch vì không có gì sai với cú pháp của chúng.

Tổng quan nhanh về Lỗi thời gian chạy Java

· Lỗi thời gian chạy trong Java là gì?
· Lỗi thời gian chạy VS Lỗi thời gian biên dịch
· Các loại lỗi thời gian chạy
· Lỗi thời gian chạy xuất hiện như thế nào?
· Tôi có cần ném Lỗi Thời gian chạy không
· Điều gì xảy ra khi bạn không bắt được Ngoại lệ Thời gian chạy
· Ví dụ về Lỗi Thời gian chạy

Lỗi thời gian chạy trong Java là gì?

Các lỗi xảy ra tại thời điểm thực hiện chương trình được gọi là lỗi thời gian chạy. Những loại lỗi này không thể được phát hiện tại thời điểm biên dịch vì không có gì sai với cú pháp của chúng. Vì vậy, lỗi Thời gian chạy xảy ra khi chương trình đã biên dịch thành công mà không đưa ra bất kỳ lỗi nào và tạo tệp “.class”. Tuy nhiên, chương trình không thực hiện đúng. Các lỗi này được phát hiện trong thời gian chạy hoặc tại thời điểm thực hiện chương trình.

Trình biên dịch Java không phát hiện lỗi thời gian chạy vì trình biên dịch Java không có bất kỳ kỹ thuật nào để bắt các lỗi này vì nó không có sẵn tất cả thông tin thời gian chạy. Lỗi thời gian chạy được bắt bởi Máy ảo Java (JVM) khi chương trình đang chạy.

Các lỗi thời gian chạy này được gọi là ngoại lệ và chúng kết thúc chương trình một cách bất thường, đưa ra thông báo lỗi.

Ngoại lệ là các lỗi được đưa ra trong thời gian chạy. Chúng ta có thể sử dụng các kỹ thuật xử lý ngoại lệ trong Java để xử lý các lỗi thời gian chạy này. Trong xử lý ngoại lệ, đoạn mã mà lập trình viên nghĩ có thể tạo ra lỗi được đặt bên trong khối thử và lập trình viên có thể bắt lỗi bên trong khối bắt.

Lỗi thời gian chạy VS Lỗi thời gian biên dịch

Lỗi thời gian biên dịch thường đề cập đến các lỗi tương ứng với ngữ nghĩa hoặc cú pháp. Lỗi thời gian chạy đề cập đến lỗi mà chúng tôi gặp phải trong quá trình thực thi mã trong thời gian chạy . Chúng ta có thể dễ dàng sửa lỗi thời gian biên dịch trong quá trình phát triển mã. Trình biên dịch không thể xác định lỗi thời gian chạy.

phát hiện

Trình biên dịch có thể dễ dàng phát hiện lỗi thời gian biên dịch trong quá trình phát triển mã. Trình biên dịch không thể dễ dàng phát hiện lỗi thời gian chạy. Vì vậy, chúng ta cần xác định nó trong quá trình thực thi mã.

Thẩm quyền giải quyết

Lỗi thời gian biên dịch thường đề cập đến các lỗi tương ứng với ngữ nghĩa hoặc cú pháp. Lỗi thời gian chạy đề cập đến lỗi không được trình biên dịch phát hiện nhưng chúng tôi gặp phải chúng trong quá trình thực thi mã (trong thời gian chạy).

sự va chạm

Lỗi thời gian biên dịch là lỗi ngữ nghĩa hoặc lỗi cú pháp, chúng ngăn mã chạy (biên dịch) vì nó phát hiện một số lỗi cú pháp. Wheares Runtime Errors ngăn không cho mã thực thi hoàn chỉnh.

cố định

Chúng ta có thể dễ dàng sửa lỗi thời gian biên dịch trong quá trình phát triển mã. Trình biên dịch không thể xác định lỗi thời gian chạy. Nhưng chúng ta có thể sửa nó sau khi thực thi mã và xác định mã trước đó.

Các loại lỗi thời gian chạy

Có nhiều loại lỗi thời gian chạy mà chúng ta có thể gặp phải tại thời điểm thực hiện chương trình. Một số lỗi thời gian chạy thường gặp được liệt kê dưới đây:

Lỗi nhập liệu : Lỗi đầu vào-đầu ra

Có vô số cách mà đầu vào của người dùng có thể làm hỏng một ứng dụng.

Trên bảng nhận xét dựa trên HTML, người dùng được phép vô tình gửi một dấu chưa được mã hóa nhỏ hơn (<) hoặc lớn hơn (>) có khả năng làm hỏng hoàn toàn khả năng hiển thị của trang web đó. Tương tự, các hệ thống xử lý văn bản được xây dựng để mong đợi tất cả đầu vào ở định dạng ASCII có thể chấm dứt sớm nếu chúng nhận được biểu tượng cảm xúc hoặc đầu vào ký tự không chuẩn.

Bất chính hơn, phương thức tấn công yêu thích của tin tặc là SQL injection , ẩn một truy vấn cơ sở dữ liệu thực thi có hại bên trong một trường nhập liệu vô thưởng vô phạt. Điều này không chỉ có thể khiến ứng dụng bị lỗi mà còn có khả năng từ bỏ quyền kiểm soát toàn bộ lớp dữ liệu.

Quá trình làm sạch đầu vào hoặc lọc dữ liệu , chuyển đổi phổ rộng dữ liệu có khả năng được nhập vào các ứng dụng thành một phạm vi giá trị an toàn mà chương trình hiểu được. Việc sử dụng các thư viện như vậy giúp giảm thiểu lỗi thời gian chạy do lỗi vệ sinh đầu vào gây ra.

Các khung công tác Java phổ biến như Apache BVal và Trình xác thực Hibernate thực hiện làm sạch đầu vào dựa trên chú thích đơn giản và chúng dễ dàng tích hợp vào bất kỳ ứng dụng dựa trên Java nào.

Logic được triển khai kém

Chỉ vì mã biên dịch không có nghĩa là nó hoạt động bình thường. Mã thường chứa các vấn đề logic khiến ứng dụng bị lỗi khi chạy.

Java chứa một cấu trúc dựng sẵn để xử lý một lớp các lỗi thời gian chạy liên quan đến mã phổ biến, được gọi là RuntimeException hoặc ngoại lệ không được kiểm tra. Java 17 xác định 78 lỗi như vậy chỉ trong SDK và các dự án và khung khác cũng xác định thêm các lỗi RuntimeException của riêng chúng.

  • ngoại lệ thời gian chạy
  • ArrayIndexOutOfBoundException
  • ConcurrentModificationException
  • ClassCastException
  • …

Ít nhất, mọi ứng dụng nên bao gồm một khai thác ngoại lệ chung có thể bắt mọi RuntimeException có thể xảy ra, ghi lại lỗi và cho phép chuỗi thực thi có vấn đề chết thay vì hủy bỏ toàn bộ ứng dụng.

Không đủ tài nguyên thời gian chạy

Các nhà phát triển phần mềm không đổ lỗi cho mọi loại lỗi thời gian chạy xảy ra. Nhiều lỗi thời gian chạy trong Java liên quan đến các giới hạn tài nguyên do sự cố với cơ sở hạ tầng bên dưới gây ra. Các ví dụ bao gồm: hết thời gian chờ mạng, hết điều kiện bộ nhớ, sử dụng quá mức CPU hoặc không thể lên lịch cho một luồng trên bộ xử lý.

Một cách để tránh lỗi thời gian chạy liên quan đến tài nguyên là sử dụng công cụ kiểm tra tải, chẳng hạn như JMeter hoặc LoadRunner, trong đường dẫn CI/CD của ứng dụng. Nếu các công cụ này phát hiện ra vấn đề về hiệu suất có thể xảy ra, thì chúng có thể dừng ứng dụng trước khi ứng dụng tiếp tục chuyển sang quá trình triển khai sản xuất.

Tải của một số ứng dụng thay đổi đáng kể. Ví dụ: một ứng dụng dịch vụ tài chính có thể tải ổn định trong hầu hết thời gian nhưng lại cực kỳ bận vào cuối ngày giao dịch. Một dịch vụ thuế có thể đạt mức tải cao nhất trước thời hạn nộp đơn nhưng tải tương đối ít trong thời gian còn lại của năm.

Các nhóm DevOps phải giám sát các chỉ số hiệu suất của họ bằng các công cụ để phát hiện trước và giảm thiểu các lỗi thời gian chạy liên quan đến tài nguyên. Ví dụ về các công cụ như vậy bao gồm JDK Flight Recorder và Java Mission Control .

Đối với các ứng dụng có khối lượng công việc hoàn toàn không thể đoán trước, hãy sử dụng công nghệ cân bằng tải dựa trên đám mây để phân bổ tài nguyên một cách linh hoạt. Điều này giúp loại bỏ cả tài nguyên được phân bổ dưới mức và cái bẫy mua phần cứng đắt tiền, hiếm khi được sử dụng.

Cấu hình tài nguyên bên ngoài

Các ứng dụng doanh nghiệp hiếm khi tồn tại trong một bong bóng bị cô lập. Chúng thường tương tác với mọi thứ từ cơ sở dữ liệu NoSQL và hệ thống quan hệ đến hàng đợi Kafka và API RESTful. Thật không may, nếu ứng dụng của bạn không thể kết nối với một hệ thống bên ngoài được yêu cầu, điều này chắc chắn sẽ dẫn đến lỗi thời gian chạy.

Tài nguyên bên ngoài có thể gây ra lỗi thời gian chạy nếu bất kỳ tình huống nào sau đây xảy ra mà không có bản cập nhật tương ứng cho chương trình gọi:

  • địa chỉ IP thay đổi;
  • thông tin đăng nhập thay đổi;
  • thay đổi cấu hình tường lửa; hoặc
  • hệ thống bên ngoài ngừng hoạt động để bảo trì.

Liên quan, các công cụ kỹ thuật hỗn loạn chấm dứt ngẫu nhiên các quy trình mà ứng dụng phụ thuộc vào. Những công cụ như vậy buộc các nhà phát triển phải viết mã đáp ứng và linh hoạt ngay cả khi các hệ thống bên ngoài bị lỗi.

Vấn đề cố hữu với các tài nguyên bên ngoài là các nhà phát triển không thể kiểm soát chúng — nhưng họ có thể kiểm soát cách ứng dụng phản hồi khi các tài nguyên bên ngoài đó bị lỗi. Dự đoán các lỗi thời gian chạy do các hệ thống bạn không kiểm soát tạo ra và viết các ứng dụng phản hồi nhanh khi các hệ thống bên ngoài đó gặp sự cố.

Lỗ hổng thư viện của bên thứ ba

Bất kỳ ứng dụng doanh nghiệp không cần thiết nào cũng bao gồm hàng tá phụ thuộc vào thư viện của bên thứ ba để thực hiện các chức năng như ghi nhật ký, giám sát, xác thực đầu vào, xử lý biểu mẫu, v.v.

Thật không may, bất kỳ lỗi nào trong thư viện của bên thứ ba đều trở thành lỗi trong ứng dụng mà bạn triển khai. Điều này đã trở thành hiện thực một cách khó chịu đối với thế giới Java vào tháng 12 năm 2021, khi một lỗ hổng chèn LDAP trong thư viện Log4j 2 được sử dụng rộng rãi đã buộc các JVM trên toàn thế giới phải ngoại tuyến.

Một cách để giảm thiểu khả năng các phụ thuộc phần mềm đưa lỗi thời gian chạy vào các ứng dụng là chỉ sử dụng các thư viện đáng tin cậy từ các tổ chức như Apache hoặc Eclipse.

Một biện pháp bảo vệ khác là cập nhật thường xuyên các phần phụ thuộc của ứng dụng lên phiên bản mới nhất ngay khi có bản cập nhật.

Cuối cùng, hãy lưu ý đến các yếu tố phụ thuộc cấp hai hoặc cấp ba — những yếu tố mà chính các yếu tố phụ thuộc chính của bạn dựa vào — và nhận thức được mọi rủi ro mà chúng mang lại.

Trong thế giới phát triển phần mềm, “hoàn hảo” là kẻ thù của “hoàn thành”. Không có chương trình nào miễn nhiễm với mối đe dọa về lỗi thời gian chạy không lường trước được. Tuy nhiên, khi các nhà phát triển doanh nghiệp nâng cao nhận thức về các nguyên nhân có thể xảy ra và thực hiện các bước để giảm thiểu các mối đe dọa tiềm ẩn, họ có thể tạo ra phần mềm giảm thiểu khả năng gặp phải lỗi thời gian chạy.

Làm thế nào lỗi thời gian chạy xuất hiện?

Chúc mừng! Nếu dấu nhắc lệnh của bạn trông như thế này:

Sau đó, bạn đã biên dịch thành công chương trình của mình thành mã byte Java, nghĩa là không có vấn đề về cú pháp nào với mã của bạn! Tuy nhiên, như tên tệp ngụ ý, khi chúng tôi chạy chương trình này:

Bây giờ chúng tôi đã gặp lỗi thời gian chạy. Lỗi thời gian chạy thường xảy ra khi có điều gì đó không đúng về mặt logic với mã của bạn. Tài liệu này sẽ giải thích cách đọc và sửa lỗi thời gian chạy.

Đây là những phần chính của lỗi thời gian chạy

Ngoại lệ trong luồng “chính” : Phần này xuất hiện đối với hầu hết các lỗi thời gian chạy. Nó chỉ cho bạn biết rằng ngoại lệ đã xảy ra trong phương thức chính, điều này sẽ xảy ra mọi lúc.

java.lang.ArrayIndexOutOfBoundsException: 5 : Đây là lỗi đã xảy ra. Tên của lỗi thường sẽ cho bạn ý tưởng về những gì có thể đã xảy ra. Trong trường hợp này, chúng tôi biết nó xử lý các mảng và đi ra khỏi không gian được phân bổ cho một mảng.

at RunTimeErrors.main(RunTimeErrors.java:10) : Đây được gọi là theo dõi ngăn xếp, cho bạn biết danh sách các phương thức đang thực thi khi xảy ra lỗi.

  • RunTimeErrors.main cho chúng ta biết rằng lỗi này xảy ra trong phương thức chính của lớp RunTimeErrors.
  • RunTimeErrors.java:10 cho chúng tôi biết điều này xảy ra trong tệp nào và nó xảy ra ở dòng nào. Trong trường hợp này, điều này đã xảy ra trong lớp chính của chúng tôi ở dòng 10 .

Đôi khi, bạn cần thực hiện kiểm tra để quyết định có ném ngoại lệ thời gian chạy hay không nếu hệ thống không thể thực hiện việc đó một mình, thường là khi làm việc với IllegalArgumentException, nhưng hầu hết thời gian bạn không cần thực hiện kiểm tra vì đây là một phần của kiểm tra thời gian chạy tiêu chuẩn mà Java thực hiện cho bạn.

hãy lấy NullPulumException làm ví dụ:

if(t == null) 
 throw new NullPointerException();

if(t != null) {
  // work with t reference
}

Điều gì xảy ra khi bạn không nắm bắt được ngoại lệ Thời gian chạy? Vì trình biên dịch không thực thi các đặc tả ngoại lệ cho những thứ này, nên khá hợp lý khi RuntimeException có thể thấm vào phương thức main( ) của bạn mà không bị bắt. Để xem điều gì xảy ra trong trường hợp này, hãy thử ví dụ sau:

//: exceptions/NeverCaught.java 
// Ignoring RuntimeExceptions. 
// {ThrowsException} 
public class NeverCaught { 
 static void f() { 
 throw new RuntimeException("From f()"); 
 } 
 static void g() { 
 f(); 
 } 
 public static void main(String[] args) { 
 g(); 
 } 
} ///:~

Exception in thread "main" Java.lang.RuntimeException: From f() 
    at NeverCaught.f(NeverCaught.Java:7) 
    at NeverCaught.g(NeverCaught.Java:10) 
    at NeverCaught.main(NeverCaught.Java:13)

Hãy nhớ rằng chỉ có thể bỏ qua các ngoại lệ của loại RuntimeException (và các lớp con) trong mã hóa của bạn, vì trình biên dịch thực thi cẩn thận việc xử lý tất cả các ngoại lệ đã kiểm tra. Lý do là RuntimeException đại diện cho một lỗi lập trình, đó là:

Một lỗi mà bạn không thể lường trước được. Ví dụ: tham chiếu null nằm ngoài tầm kiểm soát của bạn.

Một lỗi mà bạn, với tư cách là một lập trình viên, lẽ ra phải kiểm tra trong mã của mình (chẳng hạn như ArraylndexOutOfBoundsException mà bạn nên chú ý đến kích thước của mảng). Một ngoại lệ xảy ra từ điểm số 1 thường trở thành vấn đề đối với điểm

Bạn có thể thấy lợi ích to lớn của việc có các ngoại lệ trong trường hợp này là gì, vì chúng giúp ích trong quá trình sửa lỗi.

Thật thú vị khi nhận thấy rằng bạn không thể phân loại việc xử lý ngoại lệ Java như một công cụ có mục đích duy nhất. Đúng vậy, nó được thiết kế để xử lý các lỗi thời gian chạy đáng tiếc sẽ xảy ra do các lực lượng nằm ngoài tầm kiểm soát của mã của bạn, nhưng nó cũng cần thiết đối với một số loại lỗi lập trình mà trình biên dịch không thể phát hiện được.

Ví dụ về lỗi thời gian chạy

public class Temp {
public static void main(String[] args) {
  Temp t = initT();
  
  t.foo("Hi");
  
 }
 private static Temp initT() {
  return null;
 }
 public void foo(String s) {
  System.out.println(s.toLowerCase());
 }
}

Exception in thread "main" java.lang.NullPointerException
	at Temp.main(Temp.java:7)

Có cả một nhóm các loại ngoại lệ nằm trong danh mục này. Chúng luôn được Java tự động ném ra và bạn không cần đưa chúng vào các đặc tả ngoại lệ của mình. Đủ thuận tiện, tất cả chúng được nhóm lại với nhau bằng cách đặt chúng dưới một lớp cơ sở duy nhất có tên là RuntimeException , đây là một ví dụ hoàn hảo về tính kế thừa: Nó thiết lập một họ các loại có một số đặc điểm và hành vi chung. Ngoài ra, bạn không bao giờ cần phải viết một đặc tả ngoại lệ nói rằng một phương thức có thể đưa ra một RuntimeException (hoặc bất kỳ loại nào kế thừa từ RuntimeException ), bởi vì chúng là những ngoại lệ không được kiểm tra. Bởi vì chúng chỉ ra lỗi, bạn thường không bắt gặp RuntimeException- nó được xử lý tự động. Nếu bạn buộc phải kiểm tra RuntimeExceptions , mã của bạn có thể trở nên quá lộn xộn. Mặc dù bạn thường không bắt gặp RuntimeExceptions , nhưng trong các gói của riêng bạn, bạn có thể chọn ném một số RuntimeExceptions .

Xem Các ngoại lệ thời gian chạy phổ biến nhất

Học vui vẻ

Tham gia nhóm Mouad Oumous Java WhatsApp THAM GIA

Tham gia kênh Telegram Mouad Oumous THAM GIA

Hãy ủng hộ ấn phẩm của chúng tôi bằng cách theo dõi nó

GraphQL với Spring Boot Các lỗi Java Runtime phổ biến nhất Bắt đầu với Spring Boot: Hướng dẫn toàn diện cho người mới bắt đầu 10 cách đơn giản nhưng hiệu quả để cải thiện chất lượng cuộc sống của bạn Câu hỏi phỏng vấn dựa trên luồng Java8 thường gặp nhất — Phần cuối cùng Tôi kiếm được $300 bằng cách viết một cuốn sách trong 2 ngày — Đây là cách Chuỗi ngoại lệ trong Java | Xử lý ngoại lệ Cách tạo một dự án Quarkus đơn giản với tích hợp cơ sở dữ liệu