为什么Glassfish服务器在使用ZoneId创建java.time.LocalDate实例时抛出NoSuchMethodError

为什么Glassfish服务器在使用ZoneId创建java.time.LocalDate实例时抛出NoSuchMethodError,java,localdate,glassfish-5,Java,Localdate,Glassfish 5,我有这段代码,它创建了java.time.LocalDate的一个实例。我用JDK 14编译了它,它运行时没有任何错误: public void foo(Date d){ LocalDate d1 = LocalDate.ofInstant(d.toInstant(), ZoneId.systemDefault()); System.out.println("Created LocalDate from Date: "+d1); } 当我尝试在Glassfish服务

我有这段代码,它创建了java.time.LocalDate的一个实例。我用JDK 14编译了它,它运行时没有任何错误:

public void foo(Date d){
  LocalDate d1 = LocalDate.ofInstant(d.toInstant(), ZoneId.systemDefault());
  System.out.println("Created LocalDate from Date: "+d1);
}
当我尝试在Glassfish服务器5.1上运行的JSF页面的支持bean中执行相同的操作时,它抛出一个NoSuchMethodError

public void validateDateTimeLine(FacesContext fc, UIComponent ui, Object value) {
        Date then = (Date) value;
        try {
            LocalDate dthen = LocalDate.ofInstant(then.toInstant(), ZoneId.systemDefault());
            LocalDate now = LocalDate.ofInstant(Instant.now(), ZoneId.systemDefault());
            ....................................
        } catch (Exception | NoSuchMethodError e) {
            
        }
}
堆栈跟踪:

java.lang.NoSuchMethodError: java.time.LocalDate.ofInstant(Ljava/time/Instant;Ljava/time/ZoneId;)Ljava/time/LocalDate;
    at org.me.mavenlistservicedb.bean.LoginManagment.validateDateTimeLine(LoginManagment.java:176)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.sun.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:181)
    at com.sun.el.parser.AstValue.invoke(AstValue.java:289)
    at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304)
    at org.jboss.weld.module.web.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
    at org.jboss.weld.module.web.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:107)
    at javax.faces.validator.MethodExpressionValidator.validate(MethodExpressionValidator.java:109)
    at javax.faces.component.UIInput.validateValue(UIInput.java:1248)
    at javax.faces.component.UIInput.validate(UIInput.java:1037)
    at javax.faces.component.UIInput.executeValidate(UIInput.java:1334)
    at javax.faces.component.UIInput.processValidators(UIInput.java:757)
    at javax.faces.component.UIData.iterate(UIData.java:2150)
    at javax.faces.component.UIData.processValidators(UIData.java:1273)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1298)
    at javax.faces.component.UIForm.processValidators(UIForm.java:269)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1298)
    at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1332)
    at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:77)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:201)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:670)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1540)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:119)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:611)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:550)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:114)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:332)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:199)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:463)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:168)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:242)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:539)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:593)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:573)
    at java.lang.Thread.run(Thread.java:748)
有什么想法吗?


感谢虽然该方法存在于Java14中,但它不存在于Java8中的类中。我希望您使用JDK 14进行编译,但在较低版本的Java上运行它。

如果您阅读文档,即的javadoc,您会发现:

自:

九,

代码是根据Java9+运行时库编译的,但是使用-target 1.8编译的,您使用的是Java8

不要这样做,也就是说,始终确保编译时使用的运行库版本与生成的字节码版本相同

解决方案:使用编译器选项-release8,而不是-source8-target8。该选项被特别添加到Java9+编译器中,以便于针对运行库的正确版本编译旧版本的Java

推荐:有关详细信息,请参阅

更新

注释中提到,NetBeans用于编译代码。我没有NetBeans,但我相信它的功能与我使用的Eclipse非常相似,因此我将展示如何在Eclipse中修复此问题,并希望您可以自己将其应用于NetBeans

在Eclipse中,您需要在两个位置指定目标Java版本:

Eclipse中的类路径或构建路径:

命令行上的编译器符合性级别-源和目标:

在过去,这两个版本应该总是指同一个版本,例如,如图所示,其中构建路径指的是安装JDK 15的位置,并且符合性级别设置为15

从Java9和new-release编译器选项开始,您可以针对Java的旧版本,而无需安装这样的旧版本

让构建路径指向JDK 15,如果您还选中了用蓝色圈出的Use'-release'选项复选框,则可以将符合性版本更改为例如8

如果不更改生成路径以匹配法规遵从性版本,则选中“使用“-release”选项复选框非常重要


这样做将确保编译器在LocalDate.ofInstant调用上失败,因为该方法在JDK 8中不存在,即使构建路径上仍然有JDK 15。

根据Java8和关于LocalDate和LocalDateTime的更高版本,GlassFish使用jre8的版本和下一个版本有一些更改,从Java9开始

爪哇8 ofInstant是在LocalDateTime上实现的

爪哇9+

ofInstant在LocalDate上实现

为了遵循您的逻辑,您可以执行以下操作:

LocalDateTime dTime = LocalDateTime.ofInstant(then.toInstant(),ZoneId.systemDefault());
LocalDate dthen = dTime.toLocalDate();
LocalDateTime允许您获得适当的变量类型:LocalDate

公共LocalDate toLocalDate

获取此文件的LocalDate部分 日期时间。这将返回具有相同年、月和日的LocalDate 和这个日期时间一样


如果代码只是用JDK14编译的,那么生成的字节码就不会用Java8运行。要比这复杂一点,请看。是的,整个Web应用程序代码都是用JDK 14编译的,然而,Glassfish 5.1容器是在JDK8的变体上运行的,这是一个很好的解决方案,但是如果Java 8不存在该方法,为什么代码要在Java 8上编译和运行呢?谢谢,aran,这可能就是解决方案。我明天会试试,然后告诉你结果。@aran-你非常擅长使用现有的API找到解决方案。我之前也给出过这样的反馈。坚持下去@LiveandLetLive我把感伤放在这里。。。非常感谢你的话!!你是我在max尊重的那些用户中的一员,你是顶级用户中的一员。你让我学到了新的东西,这是真诚的。谢谢你的现场直播Live@aran如果IDE的编译器是v14,那么代码就不会在Java8上运行。您必须告诉IDE使用-target 8或等效IDE生成与Java 8兼容的字节码。如果这样做,还必须更改类路径以使用JDK 8安装,否则会出现类似于本问题中所示的错误。显然没有这样做,因此错误的原因是IDE配置错误。有关如何修复的信息,请参阅。如果配置正确,代码将无法编译,需要这个答案来解决这个问题。非常感谢您如此详细地阐述了这个问题。Netbean设置与Eclipse略有不同,因为NB允许用户预先设置平台,即JDK 14、JDK 8、JDK 9等等。我已经将两个这样的平台JDK 14配置为默认平台和JDK-8-update-144-for-Glassfish。对于Web应用程序开发项目,没有其他构建选项,例如-release。这次,我选择了JDK-8-update-144-for-Glassfish t
o编译源代码,当然,它将LocalDate.ofInstant标记为错误,并在我挂断自己之前切断了连接。因为我需要这个LocalDate.ofInstant功能,所以我最终使用了Aran建议的方法。再次感谢