zhao852735248 2023-02-08 11:28 采纳率: 100%
浏览 69
已结题

Linux和windows编译打包springboot项目区别

问题遇到的现象和发生背景

同样一套代码,基于springboot2.3.12开发,在linux和windows系统上使用相同版本的JDK和maven编译打包,放在linux机器上启动,windows系统打包的jar能正常启动,linux系统打包的jar启动报错,错误描述是bean找不到。两个jar包的大小不一致,但差距不大,Linux打包的jar大小为117135618字节,windows系统打包的jar大小为117135630字节。通过jar包比较工具比较两个包没有发现区别,提问:Linux系统和windows系统编译打包过程有什么区别?

遇到的现象和发生背景,请写出第一个错误信息

java.lang.NullPointerException: null

org.springframework.beans.factory.BeanCreationException

用代码块功能插入代码,请勿粘贴截图。 不用代码块回答率下降 50%

linux编译打包的代码启动时报错,通过以下形式的代码获取不到bean

public class SpringUtil implements ApplicationContextAware{ ...}

Map<String, Object> beans = SpringUtil.getApplicationContext().getBeansWithAnnotation(Mapper.class);
运行结果及详细报错内容

at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:160) ~[spring-beans-5.2.15.RELEASE.jar!/:5.2.15.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:415) ~[spring-beans-5.2.15.RELEASE.jar!/:5.2.15.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1791) ~[spring-beans-5.2.15.RELEASE.jar!/:5.2.15.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594) ~[spring-beans-5.2.15.RELEASE.jar!/:5.2.15.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) ~[spring-beans-5.2.15.RELEASE.jar!/:5.2.15.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) ~[spring-beans-5.2.15.RELEASE.jar!/:5.2.15.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.2.15.RELEASE.jar!/:5.2.15.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.2.15.RELEASE.jar!/:5.2.15.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.15.RELEASE.jar!/:5.2.15.RELEASE]

我的解答思路和尝试过的方法,不写自己思路的,回答率下降 60%

最初怀疑过windows和Linux上安装的JDK,maven版本不一致,后来尝试统一版本问题仍然没有解决。
后来怀疑git克隆到linux和windows的代码不一致,后来统一使用一套源代码分别放在linux和windows编译打包,问题仍然没有解决。
再者怀疑linux系统编译打包时和windows编码不同或者类加载顺序不同,由于缺乏相关的知识和经验,目前没办法求证。
请大家回答我的疑惑或者提供解决问题的思路,谢谢!

  • 写回答

2条回答 默认 最新

  • 嗝屁小孩纸 2023-02-09 13:25
    关注

    你好,启动过程涉及到虚拟机,排查一:看看JDK版本,JDK8和更高版本启动后,以及跨平台都有影响。
    比如自定义注解的扫描,需要获取堆栈信息判断下
    提供代码

        public static String getStackTrace() {
            StackTraceElement[] stack = new Throwable().getStackTrace();
            Stack<StackTraceElement> newStack = new Stack<>();
            for (int index = 0; index < stack.length; index++) {
                if (!stack[index].getClassName().startsWith("java.lang.reflect") &&
                        !stack[index].getClassName().startsWith("sun.reflect") &&
                        !stack[index].getClassName().startsWith("org.springframework.boot") &&
                        !stack[index].getClassName().startsWith("jdk.internal.reflect"))
                {
                    newStack.push(stack[index]);
                }
                log.trace("stack info: {}", stack[index]);
            }
            // Jar 启动会 出现 注解扫描失败
            //return stack[stack.length - 1].getClassName();
            return newStack.pop().getClassName();
        }
    

    两种结果,看完下面后你应该就意识到,SpringBoot在扫描注解的原理,其实是需要先启动成功,而启动失败大多情况下从底层上可以看到就是JDK版本的原因。
    启动失败导致Bean无法注入,或者是容器没有实例化都是有可能,因为在项目里,SpringBoot本质也是获取到当前启动类,然后再通过上面的扫描注解扫描其他包,来自动注入。
    所以原因很显而易见了。

    • 容器没有启动成功,通过堆栈信息来启动没找到,JDK版本问题
    • Bean没有注入,Maven依赖不到?注解没有发现,同名注解导致失败错误,没有注解
     /**
         * fix: 修复 Jar 包启动,注解扫描失败的问题
         * 这里如果使用 springboot 启动的话,有两种启动情况
         * 1. 项目启动方式:那么堆栈信息最后堆栈类为 启动类,本项目堆栈信息
         * stack info: cn.fyupeng.util.ReflectUtil.getStackTrace(ReflectUtil.java:31)
         * stack info: cn.fyupeng.net.AbstractRpcServer.scanServices(AbstractRpcServer.java:36)
         * stack info: cn.fyupeng.net.netty.server.NettyServer.<init>(NettyServer.java:46)
         * stack info: cn.fyupeng.UserServer.run(UserServer.java:42)
         * stack info: org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:813)
         * stack info: org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:797)
         * stack info: org.springframework.boot.SpringApplication.run(SpringApplication.java:324)
         * stack info: org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
         * stack info: org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
         * stack info: cn.fyupeng.UserServer.main(UserServer.java:35)
         *
         * 2. Jar启动方式:是先按照第一种方式启动,然后本地方法反射,最后还是在 springboot 的 JarLauncher 启动器上启动
         * stack info: cn.fyupeng.util.ReflectUtil.getStackTrace(ReflectUtil.java:31)
         * stack info: cn.fyupeng.net.AbstractRpcServer.scanServices(AbstractRpcServer.java:36)
         * stack info: cn.fyupeng.net.netty.server.NettyServer.<init>(NettyServer.java:46)
         * stack info: .UserServer.run(UserServer.java:42)
         * stack info: org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:813)
         * stack info: org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:797)
         * stack info: org.springframework.boot.SpringApplication.run(SpringApplication.java:324)
         * stack info: org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
         * stack info: org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
         * stack info: cn.fyupeng.UserServer.main(UserServer.java:35)
         * stack info: sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
         * stack info: sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
         * stack info: sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
         * stack info: java.lang.reflect.Method.invoke(Method.java:498)
         * stack info: org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
         * stack info: org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
         * stack info: org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
         * stack info: org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
         *
         * @return
         */
    

    如果真如我所言,跨平台或者JDK版本过高,推荐你把JDK降到8试试
    如仍有问题继续反馈。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 2月18日
  • 已采纳回答 2月10日
  • 创建了问题 2月8日

悬赏问题

  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥170 如图所示配置eNSP
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上