java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy排查

1、java.lang.ArrayStoreException這個的debug藉助IDEA,添加Java Exception的java.lang.ArrayStoreException斷點,這樣異常時能夠看到具體的報錯Class

2、首先進入錯誤debug的是org.springframework.cloud.netflix.eureka.config.EurekaDiscoveryClientConfigServiceBootstrapConfiguration

因爲這個版本沒有使用遠程config,所以ConfigServicePropertySourceLocator的類是找不到,所以報了異常。

繼續排查是能發現這個是BootstrapApplicationListener中的bootstrapServiceContext方法處理,異常是忽略的。

這個也是誤導了自己,耗時有點長。debug可以看下面2圖。

 

3、再次進入的是項目中的GlobalExceptionHandler類,原因也是出在這個類中。

這個類是common模塊中的統一異常處理類,其他同事做的權限security,AccessDeniedException在security的jar中。

    @ExceptionHandler(AccessDeniedException.class)
    public ObjectRestResponse accessDeniedrExceptionHandler(HttpServletResponse response, Exception ex) {
        logger.error(ex.getMessage(), ex);
        ObjectRestResponse restResponse = new ObjectRestResponse();
        restResponse.setStatus(CodeStatus.PARAM_ACCESS_FORBIDDEN.getValue());
        restResponse.setMsg(CodeStatus.PARAM_ACCESS_FORBIDDEN.getName());
        return restResponse;
    }

而該module中的pom進行了exclusion,而yunlian-truck-auth-client模塊中間接引用common模塊,所以導致GlobalExceptionHandler找不到AccessDeniedException類。

<dependency>
            <groupId>com.sinochem.yunlian.truck</groupId>
            <artifactId>yunlian-truck-auth-client</artifactId>
            <version>1.0-SNAPSHOT</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-security</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

該異常在refresh方法中進行了throw出來。

 

總結:針對java.lang.ArrayStoreException這樣的異常通過IDEA進行進行debug,以及EurekaDiscoveryClientConfigServiceBootstrapConfiguration中的這個異常處理。

---------------------------------------------------------------

具體是java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy 數組越界的異常,爲什麼是class不存在導致的,是AnnotationParser.parseClassValue把異常包裝成爲Object。

下面解釋來自https://yq.aliyun.com/articles/616541

仔細看下代碼,可以發現AnnotationParser.parseClassValue把異常包裝成爲Object

//sun.reflect.annotation.AnnotationParser.parseClassValue(ByteBuffer, ConstantPool, Class<?>)
    private static Object parseClassValue(ByteBuffer buf,
                                          ConstantPool constPool,
                                          Class<?> container) {
        int classIndex = buf.getShort() & 0xFFFF;
        try {
            try {
                String sig = constPool.getUTF8At(classIndex);
                return parseSig(sig, container);
            } catch (IllegalArgumentException ex) {
                // support obsolete early jsr175 format class files
                return constPool.getClassAt(classIndex);
            }
        } catch (NoClassDefFoundError e) {
            return new TypeNotPresentExceptionProxy("[unknown]", e);
        }
        catch (TypeNotPresentException e) {
            return new TypeNotPresentExceptionProxy(e.typeName(), e.getCause());
        }
    }

然後在sun.reflect.annotation.AnnotationParser.parseClassArray(int, ByteBuffer, ConstantPool, Class<?>)裏嘗試直接設置到數組裏

// sun.reflect.annotation.AnnotationParser.parseClassArray(int, ByteBuffer, ConstantPool, Class<?>)
result[i] = parseClassValue(buf, constPool, container);

而這裏數組越界了,ArrayStoreException只有越界的Object的類型信息,也就是上面的

java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章