JavaRush /Blog Java /Random-VI /Nghỉ giải lao #94. Đánh giá năm máy phân tích mã Java tĩn...

Nghỉ giải lao #94. Đánh giá năm máy phân tích mã Java tĩnh. Lỗi bộ nhớ heap và stack trong Java

Xuất bản trong nhóm

Đánh giá năm máy phân tích mã Java tĩnh

Nguồn: Nhà phát triển DZone thường yêu cầu nhiều chương trình khác nhau, bao gồm cả máy phân tích mã tĩnh, có thể sớm tìm và sửa mã lỗi trong quá trình phát triển. Mặc dù đánh giá mã là một công cụ vô giá trong nỗ lực này, nhưng đôi khi số lượng người đánh giá mã phải xem xét đi xem xét lại thật khó khăn. Việc này tốn rất nhiều thời gian và công sức. Điều này cũng dẫn đến việc người đánh giá thường chỉ chú ý đến những đoạn mã quan trọng đối với hoạt động của chương trình. Trong khi đó các công cụ phân tích tĩnh kiểm tra tất cả các mã với độ chính xác như nhau. Nghỉ giải lao #94.  Đánh giá năm máy phân tích mã Java tĩnh.  Lỗi bộ nhớ heap và stack trong Java - 1Tôi đã tập hợp một số bộ phân tích mã tương thích với IntelliJ IDEA. Tôi hy vọng điều này sẽ giúp bạn trong công việc của bạn.

Bộ phân tích IntelliJ IDEA tích hợp

Trình phân tích mã Java tĩnh được tích hợp trong IntelliJ IDEA không thua kém gì các công cụ phân tích tĩnh chuyên dụng. Việc tìm kiếm các đoạn mã đáng ngờ, lộn xộn hoặc không chính xác được thực hiện bằng nhiều phương pháp phân tích tĩnh khác nhau: phân tích luồng dữ liệu và khớp mẫu. IntelliJ IDEA có số lượng lớn các cuộc kiểm tra. Trên thực tế, nhiều người trong số họ không phải lúc nào cũng báo lỗi chính xác. Đúng hơn, chúng chỉ ra sự cẩu thả trong mã hoặc khả năng thay đổi nó bằng một giải pháp thay thế gọn gàng hơn. Sau khi nghiên cứu “Inspections → Java” một chút, tôi nhận thấy một điều. Việc kiểm tra các loại lỗi có thể xảy ra, các vấn đề về số và các vấn đề về xê-ri hóa có nhiều khả năng tìm ra lỗi thực sự hơn. Trong mọi trường hợp, bạn phải tự mình tiến hành các thử nghiệm và xác định thử nghiệm nào sẽ hữu ích cho dự án của bạn. Vì phân tích tĩnh được thực hiện ở chế độ chỉnh sửa mã nên trong IntelliJ IDEA bạn có thể sửa lỗi trong vòng vài giây kể từ khi chúng xảy ra. Trình chỉnh sửa ngay lập tức đánh dấu đoạn mã không chính xác. Nghỉ giải lao #94.  Đánh giá năm máy phân tích mã Java tĩnh.  Lỗi bộ nhớ Heap và Stack trong Java - 2Nó thực sự tiện lợi và mát mẻ! Ngoài ra, nếu bạn sử dụng kết hợp “Alt + Enter” trên đoạn mã đã chọn, bạn có thể chọn một trong các tùy chọn để sửa lỗi thông qua menu ngữ cảnh: Bạn cũng có thể tìm hiểu lý do chạy một kiểm tra cụ thể Nghỉ giải lao #94.  Đánh giá năm máy phân tích mã Java tĩnh.  Lỗi bộ nhớ Heap và Stack trong Java - 3. Trong một số trường hợp, điều này giúp giảm thời gian tìm kiếm: Nghỉ giải lao #94.  Đánh giá năm máy phân tích mã Java tĩnh.  Lỗi bộ nhớ Heap và Stack trong Java - 4Bạn có thể chạy phân tích theo cách thủ công bằng cách chọn “Phân tích → Kiểm tra mã”. Hoặc bạn có thể chạy kiểm tra riêng lẻ bằng cách sử dụng “Phân tích → Chạy kiểm tra theo tên”. Trước khi thực hiện việc này, hãy chỉ định phạm vi phân tích (đối với một dự án, mô-đun hoặc tệp riêng lẻ). Khi bạn chạy phân tích theo cách này, một số kiểm tra sẽ không hoạt động ở chế độ chỉnh sửa do tính phức tạp. Sau khi phân tích, kết quả sẽ được nhóm theo danh mục/thư mục trong một cửa sổ riêng. Từ cửa sổ này, bạn có thể điều hướng đến trình kích hoạt xác thực cụ thể: Nghỉ giải lao #94.  Đánh giá năm máy phân tích mã Java tĩnh.  Lỗi bộ nhớ Heap và Stack trong Java - 5IntelliJ chỉ cho phép bạn lưu kết quả phân tích ở định dạng HTML và XML. Thật không may, theo tôi, cách thuận tiện nhất là làm việc với các vấn đề được phát hiện trong chính IDE. Ghi chú. Hầu hết các tính năng của máy phân tích tĩnh đều có sẵn trong Phiên bản cộng đồng IntelliJ IDEA miễn phí.

SonarJava

SonarJava là trình phân tích mã tĩnh cho Java từ SonarSource. Danh sách các chức năng của nó bao gồm:
  • Hơn 150 quy tắc phát hiện lỗi;
  • Hơn 350 quy tắc để nhận biết mùi mã;
  • Hơn 40 quy tắc để phát hiện các lỗ hổng tiềm ẩn ;
  • Tích hợp với Maven, Gradle, Ant, Eclipse, IntelliJ IDEA, VS Code;
  • Có thể mở rộng với các quy tắc chẩn đoán tùy chỉnh;
  • Công cụ SAST chuyên dụng: hầu hết các quy tắc chẩn đoán đều được biên dịch theo CWE , CERT , OWASP .
Bạn có thể chạy phân tích cả trong nhiều IDE khác nhau (thông qua plugin SonarLint ) và riêng biệt trong SonarQube . SonarLint có thể hoạt động song song với bộ phân tích mã IntelliJ IDEA tích hợp sẵn. Nếu bạn di chuột qua một đoạn mã được đánh dấu, bạn thường có thể thấy cảnh báo từ cả hai máy phân tích: Nghỉ giải lao #94.  Đánh giá năm máy phân tích mã Java tĩnh.  Lỗi bộ nhớ Heap và Stack trong Java - 6Tất nhiên, bạn có thể xem cảnh báo trong một cửa sổ riêng: Nghỉ giải lao #94.  Đánh giá năm máy phân tích mã Java tĩnh.  Lỗi bộ nhớ Heap và Stack trong Java - 7Nhìn chung, khả năng chạy SonarJava theo nhiều cách khác nhau khiến nó trở nên hấp dẫn. Điều này cho phép các nhà phát triển tự do lựa chọn một công cụ khi viết mã.

Tìm lỗi/SpotBug

Thật không may, FindBugs đã không được cập nhật trong một thời gian dài; bản phát hành ổn định cuối cùng đã được phát hành vào năm 2015. Nhưng chúng tôi vẫn nhớ và sử dụng nó, vì nó có lẽ là trình phân tích mã Java tĩnh miễn phí nổi tiếng nhất. Nếu bạn hỏi một nhà phát triển Java về phân tích tĩnh, có thể họ sẽ nghĩ ngay đến FindBugs. Máy phân tích mã nguồn mở SpotBugs đã trở thành sự tiếp nối hợp lý của FindBugs bị bỏ rơi. Nó có tất cả ưu điểm và nhược điểm của FindBugs. Thời gian sẽ trả lời điều này là tốt hay xấu. Trong khi đó, cộng đồng phân tích đang tích cực phát triển nó. Các tính năng chính của SpotBugs:
  • Hơn 400 quy tắc phát hiện lỗi;
  • Tích hợp vào Ant, Maven, Gradle, Eclipse, IntelliJ IDEA;
  • Có thể mở rộng với các quy tắc chẩn đoán tùy chỉnh.
Để tìm mã đáng ngờ, các phương pháp tương tự được sử dụng: khớp mẫu và phân tích luồng dữ liệu. Trình phân tích phát hiện nhiều loại lỗi khác nhau có liên quan đến đa luồng, hiệu suất, lỗ hổng, làm rối mã, v.v. Trong IntelliJ IDEA, cửa sổ cảnh báo trông như thế này: Nghỉ giải lao #94.  Đánh giá năm máy phân tích mã Java tĩnh.  Lỗi bộ nhớ Heap và Stack trong Java - 8Cảnh báo có thể được nhóm theo danh mục, lớp, thư mục và mức độ tin cậy. Bạn có thể xem đồng thời các cảnh báo và tài liệu cho bất kỳ quy tắc chẩn đoán nào. Việc phân tích được bắt đầu bằng tay. Sau khi phân tích, tất cả các đoạn mã có vấn đề đều được đánh dấu cùng với các cảnh báo khác từ IntelliJ IDEA và SonarLint. Tuy nhiên, có một vấn đề. Bạn phải chạy lại phân tích để cập nhật các cảnh báo nhằm phản ánh những thay đổi bạn đã thực hiện đối với tệp. Ngoài ra còn có nhiều cảnh báo mang tính tư vấn, vì vậy máy phân tích phải được cấu hình trước khi sử dụng.

PVS-Studio

PVS-Studio dựa trên thư viện mã nguồn mở Spoon. Nó lấy mã nguồn làm đầu vào và xây dựng mô hình AST được thiết kế tốt với thông tin ngữ nghĩa. Dựa trên mô hình này, máy phân tích sử dụng các kỹ thuật hiện đại như:
  • Phân tích luồng dữ liệu;
  • Hiệu suất mang tính biểu tượng;
  • Chú thích phương pháp;
  • Phân tích dựa trên mô hình.
Hiện tại, máy phân tích sử dụng hơn 105 quy tắc chẩn đoán để xác định các lỗi mã khác nhau. Chúng bao gồm sửa lỗi đánh máy, đổi tên tham chiếu null, mã không thể truy cập, chỉ mục mảng ngoài giới hạn, vi phạm việc sử dụng hợp đồng phương thức và các lỗi khác. Bạn có thể tìm hiểu tất cả các khả năng của quy tắc chẩn đoán tại đây . Các chức năng chính của PVS-Studio:
  • Máy phân tích tập trung vào việc tìm ra các lỗi thực sự;
  • Ngoài phiên bản CLI còn có tích hợp với IntelliJ IDEA, Maven, Gradle, Jenkins, SonarQube;
  • Khả năng chạy máy phân tích ở chế độ tăng dần;
  • Trình phân tích xác định các vấn đề tương thích tiềm ẩn với API Java SE khi di chuyển dự án từ Java 8 sang các phiên bản mới hơn;
  • PVS-Studio chuyển đổi báo cáo thành nhiều định dạng thân thiện với người dùng: JSON, XML, HTML, TXT;
  • Công cụ SAST chuyên dụng: hầu hết các quy tắc chẩn đoán đều được biên dịch theo CWE , CERT , OWASP .

PMD

PMD là một máy phân tích tĩnh mã nguồn mở. Nó xác định các lỗi phát triển phổ biến: các biến không được sử dụng, các khối trống, tạo các đối tượng không cần thiết và các vấn đề khác. Máy phân tích sử dụng mã nguồn làm đầu vào. Hiện tại, PMD phân tích một tệp nguồn cho mỗi quy trình, điều này đặt ra các hạn chế về tính đầy đủ của phân tích. Các tác giả PMD khuyên nên tập hợp dự án trước khi phân tích. Điều này cho phép bạn trích xuất thông tin về các loại được sử dụng trong mã đang được phân tích. Chức năng chính của PMD:
  • Tích hợp với nhiều IDE khác nhau (IntelliJ IDEA, Eclipse, NetBeans) và các hệ thống xây dựng (Maven, Gradle, Ant);
  • Hỗ trợ các định dạng báo cáo phân tích khác nhau: SARIF, CSV, IDEA, JSON, văn bản (mặc định), XML, HTML, TextColor, v.v.;
  • Có hơn 300 mẫu quy tắc chẩn đoán. Danh mục: phong cách mã hóa, các phương pháp hay nhất, lỗi, đa luồng, hiệu suất, v.v.;
  • Cung cấp CPD (Trình phát hiện sao chép-dán) cùng với PMD phát hiện các bản sao trong mã.
Nếu chúng ta xem xét tất cả các quy tắc chẩn đoán, PMD sẽ tập trung hơn vào việc giải quyết các vấn đề về kiểu mã hóa và phát hiện các lỗi rõ ràng. Các quy tắc chẩn đoán có thể xung đột với nhau, vì vậy chúng phải được cấu hình trước khi sử dụng máy phân tích. Bạn cũng có thể chạy phân tích thông qua plugin cho IntelliJ IDEA, nhưng bạn không thể chọn từng tệp để phân tích. Cửa sổ cảnh báo trông như thế này: Nghỉ giải lao #94.  Đánh giá năm máy phân tích mã Java tĩnh.  Lỗi bộ nhớ Heap và Stack trong Java - 9Theo tôi, làm việc với các cảnh báo không thuận tiện lắm vì chúng không thể được nhóm theo tệp và thông báo không rõ ràng. Chúng chỉ xuất hiện khi bạn di chuột qua cảnh báo.

Phần kết luận

Tất nhiên, ngoài các máy phân tích đã thảo luận ở trên, còn có các giải pháp khác. Có cả chương trình trả phí (Coverity, Klockwork, JArchitect) và miễn phí (Error Prone, Infer, Checkstyle). Tất cả đều tập trung vào một điều: ngăn chặn mã không chính xác hoặc có khả năng có lỗi được đưa vào sản xuất. Tôi không có quyền đánh giá máy phân tích nào phù hợp hơn cho nhiệm vụ này. Nhưng các máy phân tích phát triển phân tích luồng dữ liệu và thực thi biểu tượng có nhiều khả năng tìm thấy lỗi thực sự trong mã hơn. Nếu bạn chọn máy phân tích tĩnh, hãy chú ý đến:
  • tích hợp vào các IDE khác nhau;
  • tích hợp vào hệ thống lắp ráp;
  • dễ dàng khởi chạy máy phân tích trên máy chủ;
  • khả năng phát hiện lỗi trong chế độ chỉnh sửa mã;
  • khả năng làm việc thuận tiện với các cảnh báo;
  • định hướng SAST;
  • tỷ lệ dương tính giả;
  • sự phức tạp của cấu hình.
  • Sự kết hợp của tất cả ưu và nhược điểm sẽ đưa bạn đến số lượng máy phân tích tĩnh mà bạn cho là tốt nhất.
Lưu ý: Tôi đã cung cấp các ví dụ về tích hợp vào IntelliJ IDEA vì tôi thường sử dụng nó.

Lỗi bộ nhớ heap và stack trong Java

Nguồn: DZone Bây giờ chúng ta sẽ xem xét các lỗi chính có thể xảy ra trong bộ nhớ heap hoặc stack của Java, nhưng trước tiên hãy nhớ ý nghĩa của hai thuật ngữ này.
  • Bộ nhớ heap là một vùng bộ nhớ đặc biệt trong đó các đối tượng java được lưu trữ.
  • Bộ nhớ ngăn xếp là vùng bộ nhớ tạm thời để lưu trữ các biến khi gọi một phương thức.
Ngoại lệ chính mô tả vấn đề về bộ nhớ heap là java.lang.OutOfMemoryError . Nghỉ giải lao #94.  Đánh giá năm máy phân tích mã Java tĩnh.  Lỗi bộ nhớ Heap và Stack trong Java - 10

Không gian vùng heap Java

Lỗi này xảy ra khi chương trình Java không phân bổ được đối tượng mới trong vùng bộ nhớ heap.

Đã vượt quá giới hạn chi phí GC

Một chương trình Java dành quá nhiều thời gian cho việc thu gom rác. Lỗi này xuất hiện khi việc thu gom rác chiếm 98% thời gian của chương trình và phục hồi ít hơn 2% dung lượng bộ nhớ.
public class OutOfMemoryErrorDemo {
    public static void main(String[] args) {
        int i = 0;
        List<String> stringList = new ArrayList<>();
        while (i < Integer.MAX_VALUE) {
            i++;
            String generatedString = new String( "Some string generated to show out of memory error example " + i);
            stringList.add(generatedString);
        }
    }
}
Ở đây stringList chứa tham chiếu đến các chuỗi được tạo của chúng tôi, do đó trình thu gom rác không thể xóa các chuỗi được tạo khỏi bộ nhớ nhưng cố gắng xóa bất kỳ rác nào khác trong ứng dụng. Nhưng điều này là không đủ.

Kích thước mảng được yêu cầu vượt quá giới hạn VM

Lỗi xảy ra khi bạn cố gắng phân bổ một mảng khi không có đủ dung lượng trong vùng heap.
public class OutOfMemoryErrorDemo {
    public static void main(String[] args) {
        // we try to create too long array
        long[] array = new long[Integer.MAX_VALUE];
    }
}

Siêu không gian

Một ngoại lệ được đưa ra với thông báo này khi không còn chỗ trong vùng siêu dữ liệu cho thông tin dữ liệu lớp.

Không có dung lượng hoán đổi (Yêu cầu byte kích thước vì lý do. Hết dung lượng hoán đổi?)

Lỗi xuất hiện khi không thể phân bổ bộ nhớ trên vùng nhớ gốc hoặc kích thước của nó không đủ.

lý do stack_trace_with_native_method

Giao diện Java gốc hoặc phương thức gốc không phân bổ được bộ nhớ trên vùng heap. StackOverFlowError - khi có quá nhiều lệnh gọi phương thức. Thông thường, một ngoại lệ được đưa ra bởi một phương thức có đệ quy bên trong nó.
public class StackOverFlowErrorDemo {

    public static void main(String[] args) {
        recursiveMethod(2);
    }

    public static int recursiveMethod(int i) {
      	// it will never stop and it allocates all stack memory
        return recursiveMethod(i);
    }
}
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION