Làm thế nào để tìm mã không sử dụng / chết trong các dự án java [đã đóng]


306

Những công cụ nào bạn sử dụng để tìm mã không sử dụng / chết trong các dự án java lớn? Sản phẩm của chúng tôi đã được phát triển trong một vài năm và rất khó để phát hiện thủ công mã không còn được sử dụng. Tuy nhiên, chúng tôi cố gắng xóa càng nhiều mã không sử dụng càng tốt.

Đề xuất cho các chiến lược / kỹ thuật chung (ngoài các công cụ cụ thể) cũng được đánh giá cao.

Chỉnh sửa: Lưu ý rằng chúng tôi đã sử dụng các công cụ bao phủ mã (Cỏ ba lá, IntelliJ), nhưng đây là những trợ giúp nhỏ. Mã chết vẫn có các bài kiểm tra đơn vị, và hiển thị như được bảo hiểm. Tôi đoán một công cụ lý tưởng sẽ xác định các cụm mã có rất ít mã khác tùy thuộc vào nó, cho phép kiểm tra thủ công tài liệu.


16
Giữ các bài kiểm tra đơn vị trong một cây nguồn riêng biệt (dù sao bạn cũng nên) và chỉ chạy các công cụ bảo hiểm trên cây sống.
agnul

5
Tôi sẽ bắt đầu với việc kiểm tra "Khai báo không sử dụng" của IDEA và bỏ chọn Bao gồm các nguồn kiểm tra . Bạn có thể nói rõ ý của bạn khi bạn nói "ít giúp đỡ" của IDEA không?
David Moles

1
Các cách để tìm mã chết: 1) không được liên kết bởi bất cứ điều gì bên ngoài. 2) đã không được sử dụng từ bên ngoài mặc dù được liên kết trong thời gian chạy. 3) Liên kết và được gọi nhưng không bao giờ được sử dụng như biến chết. 4) trạng thái logic không thể truy cập. Vì vậy, liên kết, truy cập theo thời gian, dựa trên logic, sử dụng sau khi truy cập.
Muhammad Umer

Sử dụng IntelliJ Idea và câu trả lời của tôi từ đây: stackoverflow.com/questions/22522013/, :)
BlondCode

Ngoài câu trả lời David Mole của: xem câu trả lời này stackoverflow.com/a/6587932/1579667
Benj

Câu trả lời:


40

Tôi sẽ sử dụng hệ thống đang chạy để giữ nhật ký sử dụng mã, và sau đó bắt đầu kiểm tra mã không được sử dụng trong nhiều tháng hoặc nhiều năm.

Ví dụ: nếu bạn quan tâm đến các lớp không sử dụng, tất cả các lớp có thể được ghi vào nhật ký khi các thể hiện được tạo. Và sau đó một tập lệnh nhỏ có thể so sánh các nhật ký này với danh sách đầy đủ các lớp để tìm các lớp không sử dụng.

Tất nhiên, nếu bạn đi ở cấp độ phương pháp, bạn nên ghi nhớ hiệu suất. Ví dụ, các phương thức chỉ có thể đăng nhập sử dụng đầu tiên của họ. Tôi không biết làm thế nào điều này được thực hiện tốt nhất trong Java. Chúng tôi đã thực hiện điều này trong Smalltalk, một ngôn ngữ động và do đó cho phép sửa đổi mã khi chạy. Chúng tôi sử dụng tất cả các phương thức với một cuộc gọi đăng nhập và gỡ cài đặt mã đăng nhập sau khi một phương thức đã được ghi lại lần đầu tiên, do đó sau một thời gian không có hình phạt hiệu suất nào xảy ra nữa. Có lẽ một điều tương tự có thể được thực hiện trong Java với các cờ boolean tĩnh ...


5
Tôi thích câu trả lời này nhưng có ai có ý tưởng làm thế nào để làm điều này trong Java mà không cần thêm ghi nhật ký vào mỗi lớp không? Có lẽ một số phép thuật 'Proxy'?
Lập trình viên ngoài vòng pháp luật

14
@Outlaw AOP dường như là trường hợp sử dụng hoàn hảo cho việc này.
Pascal Thivent

6
Nếu bạn hiểu cấu trúc tải lớp của ứng dụng, bạn có thể sử dụng AOP trên trình nạp lớp để theo dõi các sự kiện tải lớp. Điều này sẽ ít xâm lấn vào một hệ thống sản xuất hơn là lời khuyên trước tất cả các nhà xây dựng.
ShabbyDoo

5
Câu trả lời này là khá tốt cho một ngôn ngữ năng động nhưng khủng khiếp cho một ngôn ngữ tĩnh có thể làm NHIỀU tốt hơn. Với ngôn ngữ được nhập tĩnh (ngoài phản xạ), bạn có thể biết chính xác phương pháp nào được sử dụng và phương pháp nào không, đây là một trong những lợi thế lớn nhất của ngôn ngữ được nhập tĩnh và bạn nên sử dụng ngôn ngữ đó thay vì phương pháp có thể đọc được như được mô tả ở đây .
Bill K

4
@BillK phản ánh nhiều hơn xảy ra hơn bạn nghĩ. Ví dụ, Spring thực hiện khá nhiều phép thuật dưới vỏ bọc, bao gồm cả sự phản chiếu. Công cụ phân tích của bạn phải mô phỏng điều đó.
Thorbjørn Ravn Andersen

220

Một plugin Eclipse hoạt động hợp lý là Trình phát hiện mã không sử dụng .

Nó xử lý toàn bộ dự án hoặc một tệp cụ thể và hiển thị các phương thức mã không sử dụng / chết khác nhau, cũng như đề xuất thay đổi mức độ hiển thị (nghĩa là một phương thức công khai có thể được bảo vệ hoặc riêng tư).


Trông thật tuyệt nhưng tôi không thể làm cho nó hoạt động được - hành động "Phát hiện un ... mã" bị vô hiệu hóa và tôi không tìm cách kích hoạt nó.
Ondra ižka

1
Thực sự tìm thấy các phương thức không được sử dụng, NHƯNG cũng thấy rằng các EJB của tôi đang không được sử dụng (trong khi chúng) vì tôi đang sử dụng thiết kế mẫu đại biểu doanh nghiệp
Eildosa

Nó vẫn hoạt động trên kepler? bản phát hành nói về nhật thực 3.8: ucdetector.org/release.html
Mr_and_Mrs_D

Có vẻ là trong điều kiện làm việc hoàn hảo trên Kepler.
Erik Kaplun

4
Bạn có muốn thêm một liên kết đến thị trường marketplace.eclipse.org/content/unn cần-code-script ? Điều này giúp dễ dàng cài đặt và trả lời câu hỏi liệu nó có được hỗ trợ trên các phiên bản mới hơn của Eclipse không.
Thomas Weller

64

CodePro gần đây đã được Google phát hành với dự án Eclipse. Nó là miễn phí và hiệu quả cao. Plugin có tính năng ' Tìm mã chết ' với một / nhiều điểm nhập cảnh. Hoạt động khá tốt.


1
Sẽ không làm việc nữa với nhật thực Kepler. Sau khi cài đặt thành công thông qua trang web cập nhật, nó làm cho nhật thực sụp đổ mỗi lần.
txulu

Thật không may, có vẻ như công cụ này không nhận ra sự tồn tại của Spring, do đó, nó sẽ đánh dấu tất cả các @Components của tôi là không được sử dụng, sai
Clint Eastwood

Trở nên rất già Không hoạt động nữa Last updated this plugin March 27, 2012 nhà phát
triển.google.com/java

2
Tất cả các liên kết đã lỗi thời.
zygimantus 17/03/2016

3
Thật không may, có vẻ như Google đã bỏ mã vào dự án Eclipse và quên tất cả về nó.
Thorbjørn Ravn Andersen

30

Tôi ngạc nhiên ProGuard đã không được đề cập ở đây. Đó là một trong những sản phẩm trưởng thành nhất xung quanh.

Bảo vệ là một trình thu nhỏ, trình tối ưu hóa, obfuscator và preverifier của lớp Java miễn phí. Nó phát hiện và loại bỏ các lớp, trường, phương thức và thuộc tính không sử dụng. Nó tối ưu hóa mã byte và loại bỏ các hướng dẫn không sử dụng. Nó đổi tên các lớp, trường và phương thức còn lại bằng cách sử dụng các tên ngắn vô nghĩa. Cuối cùng, nó xác định trước mã được xử lý cho Java 6 hoặc cho Java Micro Edition.

Một số cách sử dụng ProGuard là:

  • Tạo mã nhỏ gọn hơn, để lưu trữ mã nhỏ hơn, truyền nhanh hơn qua các mạng, tải nhanh hơn và dung lượng bộ nhớ nhỏ hơn.
  • Làm cho các chương trình và thư viện khó khăn hơn để kỹ sư đảo ngược.
  • Liệt kê mã chết, vì vậy nó có thể được loại bỏ khỏi mã nguồn.
  • Nhắm mục tiêu lại và ưu tiên các tệp lớp hiện có cho Java 6 trở lên, để tận dụng tối đa lợi thế của việc tải lớp nhanh hơn của chúng.

Ví dụ ở đây cho danh sách mã chết: https://www.guardsapes.com/en/products/proguard/manual/examples#deadcode


8
Cung cấp một cách sử dụng mẫu sẽ làm cho một câu trả lời tốt hơn.
rds

1
Đọc tài liệu, tôi thấy rằng nó thu nhỏ mã không sử dụng, nhưng tôi không thể tìm thấy bất cứ nơi nào nó liệt kê nó - đã đồng ý, một ví dụ hoặc liên kết đến phần có liên quan của tài liệu, sẽ khá hữu ích!
orbfish

26

Một điều tôi đã biết phải làm trong Eclipse, trên một lớp duy nhất, là thay đổi tất cả các phương thức của nó thành riêng tư và sau đó xem những gì tôi nhận được khiếu nại. Đối với các phương thức được sử dụng, điều này sẽ gây ra lỗi và tôi đưa chúng trở về mức truy cập thấp nhất tôi có thể. Đối với các phương thức không được sử dụng, điều này sẽ gây ra cảnh báo về các phương thức không được sử dụng và những phương thức đó có thể bị xóa. Và như một phần thưởng, bạn thường tìm thấy một số phương pháp công khai có thể và nên được đặt ở chế độ riêng tư.

Nhưng nó rất thủ công.


4
Có thể không phải là câu trả lời lý tưởng nhưng điều đó thực sự thông minh.
Erik Reppen

8
Điều này thật thông minh ... cho đến khi bạn có một cuộc gọi đến nó từ một mã không được sử dụng từ một lớp khác.
Danosaure

Lặp đi lặp lại phương pháp này có thể loại bỏ các luồng mã lớn khi một phương thức được sử dụng tạo ra các phương thức khác một khi nó bị xóa.
4myle

15

Sử dụng một công cụ bao phủ thử nghiệm để sử dụng cơ sở mã của bạn, sau đó tự chạy ứng dụng chứ không phải kiểm tra.

EmmaEclemma sẽ cung cấp cho bạn các báo cáo hay về tỷ lệ phần trăm của các lớp được chạy cho bất kỳ lần chạy mã nào.


1
+1 cho nó là một điểm khởi đầu tốt nhưng hãy nhớ rằng ví dụ: các biến không được sử dụng (chưa được khai báo) cũng sẽ có màu xanh.
DerMike

13

Chúng tôi đã bắt đầu sử dụng Tìm lỗi để giúp xác định một số funk trong môi trường giàu mục tiêu của cơ sở mã hóa của chúng tôi để tái cấu trúc. Tôi cũng sẽ xem xét Cấu trúc 101 để xác định các điểm trong kiến ​​trúc cơ sở mã của bạn quá phức tạp, vì vậy bạn biết nơi đầm lầy thực sự ở đâu.


4
FindBugs không thể phát hiện mã chết và không sử dụng, chỉ các trường không sử dụng. Xem câu trả lời này .
Stefan Mücke

12

Về lý thuyết, bạn không thể xác định tìm mã không sử dụng. Có một bằng chứng toán học về điều này (tốt, đây là trường hợp đặc biệt của một định lý tổng quát hơn). Nếu bạn tò mò, hãy tìm kiếm vấn đề dừng.

Điều này có thể tự biểu hiện trong mã Java theo nhiều cách:

  • Tải các lớp dựa trên đầu vào của người dùng, tệp cấu hình, mục cơ sở dữ liệu, v.v;
  • Đang tải mã bên ngoài;
  • Chuyển cây đối tượng đến thư viện của bên thứ ba;
  • Vân vân.

Điều đó đang được nói, tôi sử dụng IDEA IntelliJ làm IDE lựa chọn của mình và nó có các công cụ phân tích mở rộng cho các phụ thuộc tìm kiếm giữa các mô-đun, phương thức không sử dụng, thành viên không sử dụng, lớp không sử dụng, v.v. Nó khá thông minh giống như một phương thức riêng tư không được gọi là được gắn thẻ không sử dụng nhưng một phương pháp công cộng đòi hỏi phân tích sâu rộng hơn.


1
Cảm ơn về thông tin bạn vừa nhập. Chúng tôi đang sử dụng IntelliJ và đang nhận được sự giúp đỡ ở đó. Đối với vấn đề dừng và không thể giải quyết được, tôi quen thuộc với lý thuyết này, nhưng chúng tôi không cần phải có một giải pháp xác định.
knatten

12
Câu mở đầu quá mạnh. Như với Vấn đề Ngừng (cũng thường bị trích dẫn sai / lạm dụng), không có giải pháp chung hoàn chỉnh, nhưng có rất nhiều trường hợp đặc biệt khả thi để phát hiện.
joel.neely

9
Mặc dù không có giải pháp chung cho các ngôn ngữ có eval và / hoặc phản ánh, nhưng có rất nhiều trường hợp mã không thể truy cập được.
pjc50

1
Nếu không có sự phản chiếu và với mã nguồn đầy đủ, bất kỳ ngôn ngữ nào được nhập tĩnh sẽ giúp việc tìm kiếm tất cả các mã không được sử dụng trở nên khá dễ dàng.
Bill K

Bạn không thể tìm thấy điều đó có thể truy cập được bằng phản xạ hoặc bởi người gọi bên ngoài, nhưng bạn có thể tìm thấy mã có thể chứng minh được không thể truy cập tĩnh từ một điểm nhập cảnh nhất định hoặc tập hợp các điểm nhập cảnh
nafg

8

Trong Eclipse Goto Windows> Tùy chọn> Java> Trình biên dịch> Lỗi / Cảnh báo
và thay đổi tất cả chúng thành lỗi. Sửa tất cả các lỗi. Đây là cách đơn giản nhất. Vẻ đẹp là điều này sẽ cho phép bạn dọn sạch mã khi bạn viết.

Ảnh chụp màn hình Mã Eclipse:

nhập mô tả hình ảnh ở đây


5

IntelliJ có các công cụ phân tích mã để phát hiện mã không được sử dụng. Bạn nên thử tạo càng nhiều trường / phương thức / lớp càng không công khai càng tốt và điều đó sẽ hiển thị nhiều phương thức / trường / lớp không sử dụng hơn

Tôi cũng sẽ cố gắng xác định vị trí mã trùng lặp như một cách để giảm khối lượng mã.

Đề nghị cuối cùng của tôi là cố gắng tìm mã nguồn mở mà nếu được sử dụng sẽ làm cho mã của bạn đơn giản hơn.


Bất kỳ ví dụ về những công cụ này là gì?
orbfish

@orbfish Bạn có thể chạy Analyse=> Run inspection by name=>unused
Peter Lawrey

5

Phối cảnh lát cắt Cấu trúc 101 sẽ đưa ra một danh sách (và biểu đồ phụ thuộc) của bất kỳ "nhóm mồ côi" hoặc " nhóm mồ côi " nào của các lớp hoặc gói không có phụ thuộc vào hoặc từ cụm "chính".


Điều này có làm việc cho các biến / phương thức ví dụ trong một lớp không?
Joeblackdev

Làm thế nào để tôi biết nếu điều này được cho là hoạt động với ví dụ Eclipse 4.3?
Erik Kaplun

3

DCD không phải là một plugin cho một số IDE nhưng có thể được chạy từ ant hoặc độc lập. Nó trông giống như một công cụ tĩnh và nó có thể làm những gì PMD và FindBugs không thể . Tôi sẽ thử nó.

PS Như đã đề cập trong một bình luận dưới đây, Dự án hiện đang sống trong GitHub .


Điều này sẽ đi xuống dưới dạng một bình luận không trả lời
Đếm

Vui lòng cập nhật câu trả lời của bạn để xóa tuyên bố rằng DCD "có vẻ đã chết". Phiên bản 2.1 đã được phát hành 12 ngày trước . Ngoài ra, liên kết trong câu trả lời của bạn không hoạt động.
skomisa

2

Có các công cụ mã hồ sơ và cung cấp dữ liệu bảo hiểm mã. Điều này cho phép bạn thấy (như mã được chạy) bao nhiêu trong số đó đang được gọi. Bạn có thể lấy bất kỳ công cụ nào trong số này để tìm hiểu xem bạn có bao nhiêu mã mồ côi.


2
  • FindBugs là tuyệt vời cho loại điều này.
  • PMD (Project Mess dò) là một công cụ khác có thể được sử dụng.

Tuy nhiên, không thể tìm thấy các phương thức tĩnh công khai không được sử dụng trong không gian làm việc. Nếu ai biết về một công cụ như vậy thì xin vui lòng cho tôi biết.


1

Các công cụ bảo hiểm người dùng, chẳng hạn như EMMA. Nhưng nó không phải là công cụ tĩnh (tức là nó yêu cầu thực sự chạy ứng dụng thông qua kiểm tra hồi quy và thông qua tất cả các trường hợp lỗi có thể xảy ra, điều này là tốt, không thể :))

Tuy nhiên, EMMA rất hữu ích.


1

Các công cụ bảo hiểm mã, chẳng hạn như Emma, ​​Cobertura và Cỏ ba lá, sẽ ghi lại mã của bạn và ghi lại phần nào của nó được gọi bằng cách chạy một bộ thử nghiệm. Điều này rất hữu ích, và nên là một phần không thể thiếu trong quá trình phát triển của bạn. Nó sẽ giúp bạn xác định bộ kiểm tra của bạn bao gồm mã của bạn tốt như thế nào.

Tuy nhiên, điều này không giống như xác định mã chết thực sự. Nó chỉ xác định mã được bao phủ (hoặc không được bảo hiểm) bằng các thử nghiệm. Điều này có thể cung cấp cho bạn dương tính giả (nếu các thử nghiệm của bạn không bao gồm tất cả các kịch bản) cũng như âm tính giả (nếu các thử nghiệm của bạn mã truy cập thực sự không bao giờ được sử dụng trong kịch bản trong thế giới thực).

Tôi tưởng tượng cách tốt nhất để thực sự xác định mã chết là sử dụng mã của bạn bằng một công cụ bảo hiểm trong môi trường chạy trực tiếp và phân tích phạm vi bảo hiểm mã trong một khoảng thời gian dài.

Nếu bạn đang chạy trong một môi trường dự phòng cân bằng tải (và nếu không, tại sao không?) Thì tôi cho rằng sẽ hợp lý khi chỉ sử dụng một phiên bản của ứng dụng của bạn và định cấu hình bộ cân bằng tải của bạn sao cho một phần ngẫu nhiên, nhưng nhỏ người dùng của bạn chạy trên ví dụ cụ của bạn. Nếu bạn thực hiện việc này trong một khoảng thời gian dài (để đảm bảo rằng bạn đã bao quát tất cả các tình huống sử dụng trong thế giới thực - các biến thể theo mùa như vậy), bạn sẽ có thể xem chính xác các khu vực mã của bạn được truy cập theo cách sử dụng trong thế giới thực và phần nào thực sự không bao giờ được truy cập và do đó mã chết.

Cá nhân tôi chưa bao giờ thấy điều này được thực hiện và không biết làm thế nào các công cụ nói trên có thể được sử dụng để tạo công cụ và phân tích mã không được gọi thông qua bộ kiểm tra - nhưng tôi chắc chắn rằng chúng có thể.


1

Có một dự án Java - Bộ phát hiện mã chết (DCD). Đối với mã nguồn, nó dường như không hoạt động tốt, nhưng đối với tệp .jar - nó thực sự tốt. Ngoài ra, bạn có thể lọc theo lớp và theo phương pháp.



0

Eclipse có thể hiển thị / đánh dấu mã không thể đạt được. JUnit có thể hiển thị cho bạn phạm vi bảo hiểm mã, nhưng bạn cần một số thử nghiệm và phải quyết định xem thử nghiệm có liên quan có bị thiếu hay mã thực sự không được sử dụng.


3
Eclipse sẽ chỉ cho bạn biết nếu phạm vi của phương thức là cục bộ (tức là riêng tư); và thậm chí sau đó bạn không thể chắc chắn 100% ... với phương thức riêng tư phản chiếu có thể được gọi từ bên ngoài.
p3t0r

0

Tôi tìm thấy công cụ bảo hiểm Cỏ ba lá có mã công cụ và làm nổi bật mã được sử dụng và không được sử dụng. Không giống như Google CodePro Analytics, nó cũng hoạt động cho WebApplecting (theo kinh nghiệm của tôi và tôi có thể không chính xác về Google CodePro).

Hạn chế duy nhất mà tôi nhận thấy là nó không tính đến các giao diện Java.


Afaict, nó là một công cụ CI phía máy chủ không miễn phí.
Erik Kaplun

0

Tôi sử dụng Doxygen để phát triển bản đồ gọi phương thức để định vị các phương thức không bao giờ được gọi. Trên biểu đồ, bạn sẽ tìm thấy các đảo của cụm phương thức mà không có người gọi. Điều này không làm việc cho các thư viện vì bạn luôn cần bắt đầu từ một số điểm vào chính.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.