如何解决勺子因利亚根据环境Docker 和本地 Spring Boot不解析 CtExecutableReference 类型和声明类型
美好的一天。
我在我的 Java 项目中使用 Spoon 分析库时遇到了一个非常奇怪的问题。 在不同环境下使用 Spoon Launcher 运行相同代码时,我得到不同的解析结果
- 1 环境 - 从 Intellij IDEA 本地运行的 Spring Boot 项目
- 2 环境 - 在 Docker 容器中运行的相同 Spring Boot 项目
在本地运行的 Spring Boot 项目中 - 一切正常,但是当我在 Docker 中运行相同的代码时 - 我在 null
和 CtExecutableReference.getType()
中得到 CtExecutableReference.getDeclaredType()
值
我在 GitHub 上打开了问题 - https://github.com/INRIA/spoon/issues/3926
详情如下
我的 Spoon 版本是 8.2.0。 (来自 Maven 仓库)
我正在尝试解析(构建 AST)来自 this GitHub repository 的代码 我在解析 this class 时遇到了麻烦 这里有以下几行
...
@Service
public class ValueServices {
private ValuesRepository valuesRepository;
private Queue<Values> queue;
@Autowired
public ValueServices(ValuesRepository valuesRepository) {
super();
this.valuesRepository = valuesRepository;
this.queue = new LinkedList<Values>();
}
public List<Values> getAllValues() {
List<Values> values = new ArrayList<>();
this.valuesRepository.findAll().forEach(values::add);
return values;
}
...
}
当我运行分析并尝试为 CtExecutableReference
语句的 findAll()
方法解析 this.valuesRepository.findAll().forEach(values::add)
时,我得到 null
和 getType()
的 getDeclaredType()
值在 Docker 中运行我的项目时。
在本地运行时,getType()
和 getDeclaredType()
都具有非空值
解析其他项目中其他类似的代码块时也会出现同样的问题。 例如here
@Service
public class BetService {
public static final String DATE_FORMAT_Now = "yyyy-MM-dd HH";
public static final String DATE_FORMAT_Now_WITH_HOUR_MIN = "yyyy-MM-dd HH:mm:ss";
private BetRepository betRepository;
@Autowired
public BetService(BetRepository betRepository) {
super();
this.betRepository = betRepository;
}
public List<Bet> getAllBets() {
List<Bet> bets = new ArrayList<Bet>();
this.betRepository.findAll().forEach(bets::add);
return bets;
}
}
在 Docker 中运行时,带有 this.betRepository.findAll()
的语句在 getType
和 getDeclaredType
中都为 null,但在本地环境中可以。
同时 following code 在两种环境中都被很好地解析
public class BetRepositoryTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private BetRepository betRepository;
@Test
public void test() {
Bet bet = new Bet("2018-07-06 12:56","WIN",103333,1082,500.5);
entityManager.persist(bet);
entityManager.flush();
List<Bet> bets = betRepository.findByCustomerId(bet.getCustomerId());
assertthat(bet.getCustomerId() == bets.get(0).getCustomerId());
}
}
和语句 betRepository.findByCustomerId()
解析正常,并且在 Docker 和本地 Spring Boot 运行中都具有必要的类型信息。
我仔细检查了本地测试 - 一切正常 - 从 IDE 在测试中运行代码或从 IDE 启动 Spring Boot 项目并通过从 Web UI 调用服务初始化分析 - 一切正常,按预期工作。
但是当我构建 Docker 镜像时 - 我的类型和声明类型都为 null。
我正在使用以下代码运行 Spoon 分析
private SourceCodemetamodel buildmetamodelForFiles(Collection<File> javaFiles) {
Launcher spoonAPI = new Launcher();
log.debug("Spoon environment - {}",ToStringBuilder.reflectionToString(spoonAPI.getEnvironment()));
log.debug("Spoon model builder - {}",ToStringBuilder.reflectionToString(spoonAPI.getModelBuilder()));
Set<String> inputResources = new HashSet<>();
for (File javaFile: javaFiles) {
String javaDir = JavaFileUtils.getJavaFileStorageRootPath(javaFile);
if (StringUtils.isNotBlank(javaDir) && !inputResources.contains(javaDir)) {
spoonAPI.addInputResource(javaDir);
inputResources.add(javaDir);
}
else if (StringUtils.isBlank(javaDir)) {
spoonAPI.addInputResource(javaFile.getAbsolutePath());
}
}
spoonAPI.buildModel();
CtModel ctModel = spoonAPI.getModel();
Collection<CtType<?>> modelTypes = ctModel.getAllTypes();
return new SpoonSourceCodemetamodel(modelTypes,false);
}
在运行 Launcher 之前,我尝试打印它的设置。这是我得到的
2021-05-14 13:26:12.329 DEBUG 1 --- [ task-1] c.s.s.r.i.s.SpoonJavaSourceCodeAnalyzer : Spoon environment - spoon.support.StandardEnvironment@4626a7ce[errorCount=0,processingStopped=false,prettyPrintingMode=FULLYQUALIFIED,warningCount=0,sourceClasspath=<null>,preserveLineNumbers=false,copyResources=true,enableComments=true,level=ERROR,shouldCompile=false,skipSelfChecks=false,complianceLevel=8,previewFeaturesEnabled=false,outputType=classes,noclasspath=true,compressionType=GZIP,sniperMode=false,ignoreDuplicateDeclarations=false,prettyPrinterCreator=<null>,useTabulations=false,tabulationSize=4,binaryOutputDirectory=/spooned-classes]
2021-05-14 13:26:12.333 DEBUG 1 --- [ task-1] c.s.s.r.i.s.SpoonJavaSourceCodeAnalyzer : Spoon model builder - spoon.support.compiler.jdt.JDTBasedSpoonCompiler@2df98092[environment=<null>,probs=[],requestor=spoon.support.compiler.jdt.TreeBuilderRequestor@57050733,factory=spoon.reflect.factory.FactoryImpl@237d7ffa,javaCompliance=7,sources=<virtual folder>: spoon.support.compiler.VirtualFolder@42618617,templates=<virtual folder>: spoon.support.compiler.VirtualFolder@7fb32ea2,templateClasspath={},compilationunitFilters=[],sortList=true]
我正在 Java8 上运行项目 - 在两种环境中(详情如下)。 要构建 docker,我使用以下命令
FROM java:8
copY maven /maven/
ENTRYPOINT java -Xverify:none -XX:TieredStopAtLevel=1 -XX:+TieredCompilation -XX:+UseSerialGC -XX:MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=40 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=${PROFILE:-docker-dev} -jar /maven/skillcounters-sca-service-1.0-SNAPSHOT.jar
我尝试切换到不同的 Docker 基础镜像(openjdk \ alpine 等),但没有任何帮助。 我试图排除上面列出的所有 Java 运行选项(例如 -XXblabla) - 也没有帮助。
为了了解可能出现的问题,我在应用程序启动时打印了所有环境(包括 Java)数据。
这里打印的是本地环境
Apple_PubSub_Socket_Render : /private/tmp/com.apple.launchd.xCrhs0tTMM/Render
COMMAND_MODE : unix2003
HOME : /Users/sk
JAVA_MAIN_CLASS_66239 : org.codehaus.classworlds.Launcher
JAVA_MAIN_CLASS_66249 : com.skillcounters.sca.SCAServiceApplication
LANG : ru_RU.UTF-8
LC_CTYPE : ru_RU.UTF-8
LOGNAME : sk
PATH : /Users/sk/Develop/d20/db/liquibase:/Users/sk/anaconda/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
PID : 66249
PWD : /Users/sk/Develop/d20/d20-git-repo/skillcounters-sca-service/skillcounters-sca-service-impl
SecuritySESSIONID : 186a9
SHELL : /bin/bash
SSH_AUTH_SOCK : /private/tmp/com.apple.launchd.ItaWSltKcA/Listeners
TMPDIR : /var/folders/lz/gjd4j2t12_39qs0hpdjqd3sh0000gn/T/
USER : sk
xpc_FLAGS : 0x0
xpc_SERVICE_NAME : com.apple.xpc.launchd.oneshot.0x10000002.idea
__CF_USER_TEXT_ENCODING : 0x1F5:0x0:0x0
awt.toolkit : sun.lwawt.macosx.LWCToolkit
file.encoding : UTF-8
file.encoding.pkg : sun.io
file.separator : /
ftp.nonProxyHosts : local|*.local|169.254/16|*.169.254/16
gopherProxySet : false
http.nonProxyHosts : local|*.local|169.254/16|*.169.254/16
java.awt.graphicsenv : sun.awt.CGraphicsEnvironment
java.awt.headless : true
java.awt.printerjob : sun.lwawt.macosx.CPrinterJob
java.class.path : {all dependent jars go here - excluded them not to pollute issue...}
java.class.version : 52.0
java.endorsed.dirs : /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/endorsed
java.ext.dirs : /Users/sk/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java
java.home : /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre
java.io.tmpdir : /var/folders/lz/gjd4j2t12_39qs0hpdjqd3sh0000gn/T/
java.library.path : /Users/sk/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.
java.runtime.name : Java(TM) SE Runtime Environment
java.runtime.version : 1.8.0_131-b11
java.specification.name : Java Platform API Specification
java.specification.vendor : Oracle Corporation
java.specification.version : 1.8
java.vendor : Oracle Corporation
java.vendor.url : http://java.oracle.com/
java.vendor.url.bug : http://bugreport.sun.com/bugreport/
java.version : 1.8.0_131
java.vm.info : mixed mode
java.vm.name : Java HotSpot(TM) 64-Bit Server VM
java.vm.specification.name : Java Virtual Machine Specification
java.vm.specification.vendor : Oracle Corporation
java.vm.specification.version : 1.8
java.vm.vendor : Oracle Corporation
java.vm.version : 25.131-b11
这是在 Docker 环境中打印的内容
CA_CERTIFICATES_JAVA_VERSION : 20140324
HOME : /root
HOSTNAME : e297584466e8
JAVA_DEBIAN_VERSION : 8u111-b14-2~bpo8+1
JAVA_HOME : /usr/lib/jvm/java-8-openjdk-amd64
JAVA_VERSION : 8u111
LANG : C.UTF-8
PATH : /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PID : 8
PROFILE : prod
PWD : /
awt.toolkit : sun.awt.X11.XToolkit
file.encoding : UTF-8
file.encoding.pkg : sun.io
file.separator : /
java.awt.graphicsenv : sun.awt.X11GraphicsEnvironment
java.awt.headless : true
java.awt.printerjob : sun.print.PSPrinterJob
java.class.path : /maven/skillcounters-skill-service-1.0-SNAPSHOT.jar
java.class.version : 52.0
java.endorsed.dirs : /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/endorsed
java.ext.dirs : /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext:/usr/java/packages/lib/ext
java.home : /usr/lib/jvm/java-8-openjdk-amd64/jre
java.io.tmpdir : /tmp
java.library.path : /usr/java/packages/lib/amd64:/usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib
java.protocol.handler.pkgs : org.springframework.boot.loader
java.runtime.name : OpenJDK Runtime Environment
java.runtime.version : 1.8.0_111-8u111-b14-2~bpo8+1-b14
java.security.egd : file:/dev/./urandom
java.specification.name : Java Platform API Specification
java.specification.vendor : Oracle Corporation
java.specification.version : 1.8
java.vendor : Oracle Corporation
java.vendor.url : http://java.oracle.com/
java.vendor.url.bug : http://bugreport.sun.com/bugreport/
java.version : 1.8.0_111
java.vm.info : mixed mode
java.vm.name : OpenJDK 64-Bit Server VM
java.vm.specification.name : Java Virtual Machine Specification
java.vm.specification.vendor : Oracle Corporation
java.vm.specification.version : 1.8
java.vm.vendor : Oracle Corporation
java.vm.version : 25.111-b14
任何帮助将不胜感激
解决方法
我在启用 Spoon Launcher 日志记录时找到了一些线索,将其设置为“全部”
这是我在 Docker 环境中得到的
...
The method findAll() is undefined for the type ValuesRepository at /opt/skillcounters/filestorage/github/vipinjo/assignment-consumer/work-tree/d4e050cf3566981ba386e336c5889f8d107abfbb/src/main/java/com/vipinjoseph/assignmentconsumer/service/ValueServices.java:32
并且在本地环境中这些警告不会显示...
存在一些类似于 https://www.programmersought.com/article/47106442813/
的类路径问题经过将近一天的努力,我找到了解决方案
- 使用 Spoon 9.0.0 或更高版本并带有 this 修复
- 使用 Spoon Launcher 的父类加载器创建类加载器
- 将每个 *.jar 文件直接包含到类加载器 URL 类路径中(不是包含 jar 的目录,而是传递给类加载器的单个 URL 中的每个 jar)
- 将此类加载器设置为 InputClassLoader
URLClassLoader urlClassLoader = URLClassLoader.newInstance(
jarUrls.toArray(new URL[0]),spoonAPI.getClass().getClassLoader()
);
spoonAPI.getEnvironment().setInputClassLoader(urlClassLoader);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。