Java代码检查工具之PMD的使用方法
小编给大家分享一下Java代码检查工具之PMD的使用方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
介绍
PMD是一个静态源代码分析器。它发现了常见的编程缺陷,如未使用的变量、空捕获块、不必要的对象创建等等。
使用方式
1、使用插件的方式
下载:File -> Settings -> Plugins -> Marketplace 搜索 “PMDPlugin” ,下载插件。
使用方法:在代码编辑框或Project 窗口的文件夹、包、文件右键,选择“Run PMD”->“Pre Defined”->“All”,对指定的文件夹、包、文件进行分析,分析结果在控制台输出。
2、maven项目引入依赖的方式
pom.xml:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.keafmd</groupId> <artifactId>pdm-test01</artifactId> <version>1.0-SNAPSHOT</version> <!--<dependencies> <dependency> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-pmd-plugin</artifactId> <version>3.14.0</version> <type>maven-plugin</type> </dependency> </dependencies>--> <!-- 用于生成错误到代码内容的链接 --> <reporting> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-pmd-plugin</artifactId> <version>3.14.0</version> </plugin> </plugins> </reporting></project>
mvn 命令执行
在项目目录打开cmd窗口,输入以下命令:
mvn pmd:pmd
分析结果为pmd.html
文件,在项目的target下的site目录下:
分析结果显示内容:
3、pmd 命令行的方式
pmd -d 源代码路径 -f xml(结果输出格式) -r 结果保存所在目录及名称 -R rulesets/java/unusedcode.xml
例子:
结果存放在制定文件目录下,格式也为命令语句指定的:
检测结果内容:
4、Java API的方式 *
官方文档
需要先引入maven依赖
项目结构
测试代码
Test01:
package com.keafmd.test01;public class Test01 { public static void main(String[] args) { int a =100; int b=29; String s ="abc"; System.out.println("hello!"); }}
Test02:
package com.keafmd.test02;public class Test02 { public static void main(String[] args) { boolean flag=true; while(flag){ flag=false; } System.out.println("123"); int a =100; int b=29; String s ="abc"; System.out.println("hello!"); }}
pmdArgs方式
命令行接口的方式
最简单的方法是使用与命令行相同的接口调用PMD
Example :
package com.keafmd;import net.sourceforge.pmd.PMD;public class Example { public static void main(String[] args) { String[] pmdArgs = { "-d", "D:/javaworkspace/pdm-test02/class="lazy" data-src", "-R", "rulesets/java/quickstart.xml", "-f", "xml", "-r", "D:/pmdreport/pmd-report.xml" }; PMD.main(pmdArgs); }}
PMDConfiguration方式
PmdExample:
package com.keafmd;import net.sourceforge.pmd.PMD;import net.sourceforge.pmd.PMDConfiguration;public class PmdExample { public static void main(String[] args) { PMDConfiguration configuration = new PMDConfiguration(); configuration.setInputPaths("D:/javaworkspace/pdm-test/class="lazy" data-src"); configuration.setRuleSets("rulesets/java/quickstart.xml"); configuration.setReportFormat("html"); configuration.setReportFile("D:/pmdreport/pmd-report.html"); PMD.doPMD(configuration); }}
Programmatically(拓展)
这使您能够更好地控制处理哪些文件,但也会更加复杂。您还可以提供自己的侦听器和呈现器。
首先,我们创建一个PMDConfiguration
。目前,这是指定规则集的唯一方法:
PMDConfiguration configuration = new PMDConfiguration();configuration.setMinimumPriority(RulePriority.MEDIUM);configuration.setRuleSets("rulesets/java/quickstart.xml");
为了支持类型解析,PMD还需要访问已编译的类和依赖项。这被称为“生长素路径”,并且在这里也进行了配置。注意:您可以指定由:
关于Unix系统或;
在Windows下。
configuration.prependClasspath("/home/workspace/target/classes:/home/.m2/repository/my/dependency.jar");
那我们需要一个规则工厂。这是使用配置创建的,同时考虑到最低优先级:
RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.createFactory(configuration);
PMD操作于DataSource
。您可以收集自己的列表FileDataSource
.
List<DataSource> files = Arrays.asList(new FileDataSource(new File("/path/to/class="lazy" data-src/MyClass.java")));
对于报告,您可以使用内置渲染器。XMLRenderer
。注意,必须通过设置适当的Writer
打电话start()
。在pmd运行之后,您需要调用end()
和flush()
。那么你的作者应该收到所有的输出。
StringWriter rendererOutput = new StringWriter();Renderer xmlRenderer = new XMLRenderer("UTF-8");xmlRenderer.setWriter(rendererOutput);xmlRenderer.start();
创建一个RuleContext
。这是上下文实例,在规则实现中是可用的。注意:当在多线程模式下运行时(这是默认的),规则上下文实例将被克隆到每个线程。
RuleContext ctx = new RuleContext();
可以选择注册报表侦听器。这样你就可以对发现的违规行为立即做出反应。您也可以使用这样的侦听器来实现您自己的呈现器。侦听器必须实现接口。ThreadSafeReportListener
并且可以通过ctx.getReport().addListener(...)
.
ctx.getReport().addListener(new ThreadSafeReportListener() { public void ruleViolationAdded(RuleViolation ruleViolation) { } public void metricAdded(Metric metric) { }
现在,所有的准备工作都完成了,PMD可以执行了。这是通过调用PMD.processFiles(...)
。此方法调用接受配置、规则集工厂、要处理的文件、规则上下文和呈现器列表。如果不想使用任何渲染器,请提供一个空列表。注意:需要显式关闭辅助路径。否则,类或JAR文件可能会保持打开状态,并且文件资源会泄漏。
try { PMD.processFiles(configuration, ruleSetFactory, files, ctx, Collections.singletonList(renderer));} finally { ClassLoader auxiliaryClassLoader = configuration.getClassLoader(); if (auxiliaryClassLoader instanceof ClasspathClassLoader) { ((ClasspathClassLoader) auxiliaryClassLoader).close(); }}
呼叫后,您需要完成渲染器end()
和flush()
。然后,您可以检查呈现的输出。
renderer.end();renderer.flush();System.out.println("Rendered Report:");System.out.println(rendererOutput.toString());
下面是一个完整的例子:
import java.io.IOException;import java.io.StringWriter;import java.io.Writer;import java.nio.file.FileSystems;import java.nio.file.FileVisitResult;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.PathMatcher;import java.nio.file.SimpleFileVisitor;import java.nio.file.attribute.BasicFileAttributes;import java.util.ArrayList;import java.util.Collections;import java.util.List;import net.sourceforge.pmd.PMD;import net.sourceforge.pmd.PMDConfiguration;import net.sourceforge.pmd.RuleContext;import net.sourceforge.pmd.RulePriority;import net.sourceforge.pmd.RuleSetFactory;import net.sourceforge.pmd.RuleViolation;import net.sourceforge.pmd.RulesetsFactoryUtils;import net.sourceforge.pmd.ThreadSafeReportListener;import net.sourceforge.pmd.renderers.Renderer;import net.sourceforge.pmd.renderers.XMLRenderer;import net.sourceforge.pmd.stat.Metric;import net.sourceforge.pmd.util.ClasspathClassLoader;import net.sourceforge.pmd.util.datasource.DataSource;import net.sourceforge.pmd.util.datasource.FileDataSource;public class PmdExample2 { public static void main(String[] args) throws IOException { PMDConfiguration configuration = new PMDConfiguration(); configuration.setMinimumPriority(RulePriority.MEDIUM); configuration.setRuleSets("rulesets/java/quickstart.xml"); configuration.prependClasspath("/home/workspace/target/classes"); RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.createFactory(configuration); List<DataSource> files = determineFiles("/home/workspace/class="lazy" data-src/main/java/code"); Writer rendererOutput = new StringWriter(); Renderer renderer = createRenderer(rendererOutput); renderer.start(); RuleContext ctx = new RuleContext(); ctx.getReport().addListener(createReportListener()); // alternative way to collect violations try { PMD.processFiles(configuration, ruleSetFactory, files, ctx, Collections.singletonList(renderer)); } finally { ClassLoader auxiliaryClassLoader = configuration.getClassLoader(); if (auxiliaryClassLoader instanceof ClasspathClassLoader) { ((ClasspathClassLoader) auxiliaryClassLoader).close(); } } renderer.end(); renderer.flush(); System.out.println("Rendered Report:"); System.out.println(rendererOutput.toString()); } private static ThreadSafeReportListener createReportListener() { return new ThreadSafeReportListener() { @Override public void ruleViolationAdded(RuleViolation ruleViolation) { System.out.printf("%-20s:%d %s%n", ruleViolation.getFilename(), ruleViolation.getBeginLine(), ruleViolation.getDescription()); } @Override public void metricAdded(Metric metric) { // ignored } }; } private static Renderer createRenderer(Writer writer) { XMLRenderer xml = new XMLRenderer("UTF-8"); xml.setWriter(writer); return xml; } private static List<DataSource> determineFiles(String basePath) throws IOException { Path dirPath = FileSystems.getDefault().getPath(basePath); PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:*.java"); List<DataSource> files = new ArrayList<>(); Files.walkFileTree(dirPath, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException { if (matcher.matches(path.getFileName())) { System.out.printf("Using %s%n", path); files.add(new FileDataSource(path.toFile())); } else { System.out.printf("Ignoring %s%n", path); } return super.visitFile(path, attrs); } }); System.out.printf("Analyzing %d files in %s%n", files.size(), basePath); return files; }}
分析结果
分析结果会根据指定格式输出在指定文件目录下。
图形界面
检测
D:\MyFile\Tool\pmd-bin-6.32.0\bin 目录下打开cmd窗口输入:
cpdgui.bat
自定义规则
D:\MyFile\Tool\pmd-bin-6.32.0\bin 目录下打开cmd窗口输入:
designer.bat
自定义规则:不能有变量为keafmd的String类型的变量
String keafmd; //这样就是不合法的。
Source:
public class KeepingItSerious { Delegator keafmd; // FieldDeclaration public void method() { String keafmd; // LocalVariableDeclaration }}
导出的自定义规则:
<rule name="myrule" language="java" message="不能有变量为keafmd的String类型的变量" class="net.sourceforge.pmd.lang.rule.XPathRule"> <description>自定义规则 </description> <priority>3</priority> <properties> <property name="version" value="2.0"/> <property name="xpath"> <value><![CDATA[//VariableDeclaratorId[@Image = "keafmd" and ../../Type[@TypeImage = "String"]]]]> </value> </property> </properties></rule>
以上是“Java代码检查工具之PMD的使用方法”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网行业资讯频道!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341