有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

爪哇岛。不解析CtExecutableReference类型和声明的类型,具体取决于环境(Docker和本地Spring引导)

你好

我在Java项目中使用Spoon分析库时遇到了一个非常奇怪的问题。 我在运行相同的代码时得到不同的解析结果,这些代码在不同的环境中使用Spoon Launcher

  • 1环境-从Intellij IDEA本地运行的Spring启动项目
  • 2环境-与在Docker容器中运行的Spring Boot项目相同

在本地运行的SpringBoot项目中——一切正常,但是当我在Docker中运行相同的代码时——我在CtExecutableReference.getType()CtExecutableReference.getDeclaredType()中得到null

我在GitHub上开始发行-https://github.com/INRIA/spoon/issues/3926

以下是详细信息

我的勺子版本是8.2.0。(来自maven repo)

我正试图从this GitHub repository解析(构建AST)代码 我在解析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;
    }

...
}

在Docker中运行我的项目时,当我运行分析并尝试为this.valuesRepository.findAll().forEach(values::add)语句的findAll()方法解析CtExecutableReference时,我得到了nullgetDeclaredType()null值。 在本地运行时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()的语句在getTypegetDeclaredType中都为空,但在本地环境中为ok

同时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()被解析为ok,并且在Docker和n local Spring引导运行中都有必要的类型信息

当从IDE运行测试中的代码或从IDE启动Spring Boot项目,并通过从Web UI调用服务初始化分析时,我仔细检查了本地测试,一切正常,并按预期工作

但是,当我构建Docker映像时,type和declaredType中的值都为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

任何帮助都将不胜感激


共 (1) 个答案

  1. # 1 楼答案

    当我将Spoon Launcher日志设置为“ALL”时,我发现了一些线索

    这是我在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/

    经过将近一天的努力,我找到了一个解决办法

    1. 使用Spoon 9.0.0或更高版本的thisfix
    2. 从Spoon Launcher使用父类加载器创建类加载器
    3. 直接包括每个*。jar文件转换为类加载器URL类路径(不是包含jar的目录,而是传递给类加载器的单个URL中的每个jar)
    4. 将此类加载器设置为InputClassLoader
                    URLClassLoader urlClassLoader = URLClassLoader.newInstance(
                                                                    jarUrls.toArray(new URL[0])
                                                                    ,spoonAPI.getClass().getClassLoader()
                                                    );
                    spoonAPI.getEnvironment().setInputClassLoader(urlClassLoader);