引起:java.lang.NoSuchFieldException:修饰符

问题描述 投票:0回答:1

我正在处理现有的旧 spring-boot 代码,同时迁移/升级到 spring-boot 2.7.16 并将 jdk 版本从 8 升级到 21 我收到此错误

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.simple.AbstractJdbcCall;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
public class CustomJDBCCall extends SimpleJdbcCall {
private final CustomCallMetaDataContext callMetaDataContext;
private static final String CALL_META_DATA_CONTEXT = "callMetaDataContext";
private static final String MODIFIERS = "modifiers";
private static final Logger LOGGER =Logger.getLogger(CustomJDBCCall.class);

public CustomJDBCCall(JdbcTemplate jdbcTemplate) throws Exception {
    super(jdbcTemplate);
    try {
        callMetaDataContext = new CustomCallMetaDataContext();
        
        // Access private field
        Field callMetaDataContextField = 
        AbstractJdbcCall.class.getDeclaredField(CALL_META_DATA_CONTEXT);
        callMetaDataContextField.setAccessible(true);

   
        Field modifiersField = Field.class.getDeclaredField(MODIFIERS);
        modifiersField.setAccessible(true);
        modifiersField.setInt(callMetaDataContextField, 
     callMetaDataContextField.getModifiers() & ~Modifier.FINAL);


        callMetaDataContextField.set(this, this.callMetaDataContext);
      } catch (NoSuchFieldException | IllegalAccessException ex) {
        LOGGER.error("Error while using custom JDBC", ex);
        throw new RuntimeException("Exception thrown overriding 
     AbstractJdbcCall.callMetaDataContext field", ex);
     } catch (Exception ex) {
        LOGGER.error("Error while using custom JDBC", ex);
        throw ex;
     }
   }

    public List<SqlParameter> getParamerters() throws Exception {
    return this.callMetaDataContext.getCallParameters();
    }
 }

在此代码中,该行抛出异常

 Field modifiersField = Field.class.getDeclaredField(MODIFIERS);

引起的:java.lang.NoSuchFieldException:修饰符 在 java.base/java.lang.Class.getDeclaredField(Class.java:2782)

之前在jdk 8中运行良好。 这是不是我编写的现有代码,我认为这里访问私有最终字段并设置值。我对么 ? 我认为在 Jdk 版本 12 及更高版本中,修改最终变量和私有变量是不可能的或禁用的,有什么解决方法吗?

java spring-boot spring-jdbc java-21
1个回答
0
投票

如果我正确地阅读了您的代码,您的

CustomJDBCCall
类就是一个“黑客”,允许您访问 JDBC 调用的参数值。

我认为你不再需要这个技巧了。在当前版本的 Spring 中,

SimpleJdbcCall
(您的类扩展)现在有一个返回参数值的
getCallParameters()
方法。

参见 https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/simple/AbstractJdbcCall.html#getCallParameters()

所以......我的建议是摆脱这个黑客。将其替换为

SimpleJdbcCall
...并使用直接
getParamerters
调用更正对
getCallParameters
(原文如此)方法的调用。

这避免了令人讨厌的反射抽象完全破坏东西。


现在我遇到了一个奇怪的异常。

org.springframework.dao.DataAccessResourceFailureException: 
    Error retrieving database meta-data; nested exception is
org.springframework.jdbc.support.MetaDataAccessException: 
    Could not get Connection for extracting meta-data; 
org.springframework.jdbc.CannotGetJdbcConnectionException: 
    Failed to obtain JDBC Connection; nested exception is
    Cannot create PoolableConnectionFactory

这看起来完全是一个不同的问题。


之前它在 JDK 8 中运行良好。

当您更改 Java 版本、Spring 版本等时,像上面这样的讨厌代码很容易被破坏。写这篇文章的人可能不应该......如果他们真的必须这样做,他们应该对其进行适当的评论,以解释他们在做什么以及为什么1

1 - 并乞求宽恕...以免编码之神用雷电打击他们!

© www.soinside.com 2019 - 2024. All rights reserved.