Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spring Framework >= 5.3.8 ASM ClassReader fails to parse class file due to InputStream optimization #27429

Closed
MichalKoziorowski-TomTom opened this issue Sep 17, 2021 · 11 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: feedback-provided Feedback has been provided type: regression A bug that is also a regression
Milestone

Comments

@MichalKoziorowski-TomTom
Copy link

MichalKoziorowski-TomTom commented Sep 17, 2021

Affects: \ spring framework >= 5.3.8

In my project, after switching from using spring boot 2.4.4 to 2.4.10 At the very beginning of start I'm getting following exception:

{"@timestamp":"2021-09-17T13:28:47.395Z","logLevel":"INFO","pid":"10","logThread":"main","logger":"com.tomtom.lns.batch.front.FrontendApp","message":"The following profiles are active: prod,kubernetes"}
{"@timestamp":"2021-09-17T13:28:47.515Z","logLevel":"WARN","pid":"10","logThread":"main","logger":"o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext","message":"Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.tomtom.lns.batch.front.FrontendApp]; nested exception is org.springframework.core.NestedIOException: ASM ClassReader failed to parse class file - probably due to a new Java class file version that isn't supported yet: class path resource [com/tomtom/lns/batch/health/HealthConfig.class]; nested exception is java.lang.IllegalArgumentException: Unsupported class file major version 21845"}
{"@timestamp":"2021-09-17T13:28:47.538Z","logLevel":"ERROR","pid":"10","logThread":"main","logger":"o.springframework.boot.SpringApplication","message":"Application run failed","stack_trace":"java.lang.IllegalArgumentException: Unsupported class file major version 21845
  at org.springframework.asm.ClassReader.<init>(ClassReader.java:199)
  at org.springframework.asm.ClassReader.<init>(ClassReader.java:180)
  at org.springframework.asm.ClassReader.<init>(ClassReader.java:166)
  at org.springframework.asm.ClassReader.<init>(ClassReader.java:287)
  at org.springframework.core.type.classreading.SimpleMetadataReader.getClassReader(SimpleMetadataReader.java:57)
  ... 39 common frames omitted
Wrapped by: org.springframework.core.NestedIOException: ASM ClassReader failed to parse class file - probably due to a new Java class file version that isn't supported yet: class path resource [com/tomtom/lns/batch/health/HealthConfig.class]; nested exception is java.lang.IllegalArgumentException: Unsupported class file major version 21845
  at org.springframework.core.type.classreading.SimpleMetadataReader.getClassReader(SimpleMetadataReader.java:60)
  at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:49)
  at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:103)
  at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.createMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:86)
  at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.getMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:73)
  at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:81)
  at org.springframework.context.annotation.ConfigurationClassParser.asSourceClass(ConfigurationClassParser.java:696)
  at org.springframework.context.annotation.ConfigurationClassParser$SourceClass.getRelated(ConfigurationClassParser.java:1090)
  at org.springframework.context.annotation.ConfigurationClassParser$SourceClass.getAnnotationAttributes(ConfigurationClassParser.java:1071)
  at org.springframework.context.annotation.ConfigurationClassParser.collectImports(ConfigurationClassParser.java:549)
  at org.springframework.context.annotation.ConfigurationClassParser.getImports(ConfigurationClassParser.java:522)
  at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:311)
  at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250)
  at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:199)
  at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:304)
  at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250)
  at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207)
  at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:175)
  ... 22 common frames omitted
Wrapped by: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.tomtom.lns.batch.front.FrontendApp]; nested exception is org.springframework.core.NestedIOException: ASM ClassReader failed to parse class file - probably due to a new Java class file version that isn't supported yet: class path resource [com/tomtom/lns/batch/health/HealthConfig.class]; nested exception is java.lang.IllegalArgumentException: Unsupported class file major version 21845
  at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:189)
  at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:331)
  at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247)
  at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311)
  at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112)
  at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746)
  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
  at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144)
  at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:771)
  at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:763)
  at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:438)
  at org.springframework.boot.SpringApplication.run(SpringApplication.java:339)
  at org.springframework.boot.SpringApplication.run(SpringApplication.java:1329)
  at org.springframework.boot.SpringApplication.run(SpringApplication.java:1318)
  at com.tomtom.lns.batch.front.FrontendApp.main(FrontendApp.java:19)
  at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java)
  at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:566)
  at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
  at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
  at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
  at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
"}

I've unpacked HealthConfig.class from built jar and saw following when reading using linux midnight commander:

compiled Java class data, version 55.0
Compiled from "HealthConfig.java"
public class com.tomtom.lns.batch.health.HealthConfig {
  public com.tomtom.lns.batch.health.HealthConfig();
  com.tomtom.lns.batch.health.ShutdownListener shutdownListener(org.springframework.context.ApplicationEventPublisher);
  com.tomtom.lns.batch.health.HealthGroupStatusNotifier stateLogger(org.springframework.context.ApplicationEventPublisher, org.springframework.boot.actuate.health.HealthEndpointGroups, org.springframework.boot.actuate.hea
}

I've tried multiple versions of spring boot and spring framework and found that issue starts in spring 5.3.8.
In that version I see that org.springframework.asm.ClassReader was modified in: #27023


@MichalKoziorowski-TomTom MichalKoziorowski-TomTom changed the title spring framework >= 3.5.8 spring framework >= 3.5.8 ASM ClassReader failed to parse class file - probably due to a new ... Unsupported class file major version 21845 Sep 17, 2021
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Sep 17, 2021
@MichalKoziorowski-TomTom
Copy link
Author

I've modified readStream() method to have more data:

  private static byte[] readStream(final InputStream inputStream, final boolean close)
      throws IOException {
    if (inputStream == null) {
      throw new IOException("Class not found");
    }
    int bufferSize = calculateBufferSize(inputStream);
    System.out.println("==========================");
    System.out.println("IS: " + inputStream.getClass().getName());
    System.out.println("bufferSize: " + bufferSize);
    try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
      byte[] data = new byte[bufferSize];
      int bytesRead;
      int readCount = 0;
      while ((bytesRead = inputStream.read(data, 0, bufferSize)) != -1) {
        outputStream.write(data, 0, bytesRead);
        readCount++;
        System.out.println("bytesRead: " + bytesRead);
      }

      outputStream.flush();
      System.out.println("readCount: " + readCount);
      if (readCount == 1) {
        System.out.println("data: " + Arrays.toString(data));
        System.out.println("outputStream.toByteArray(): " + Arrays.toString(outputStream.toByteArray()));
        System.out.println("==========================");
        return data;
      }
      System.out.println("==========================");
      return outputStream.toByteArray();
    } finally {
      if (close) {
        inputStream.close();
      }
    }
  }

For the failed class I see following result:

IS: sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream
bufferSize: 2889
bytesRead: 2889
readCount: 1
data: [85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 0, 47, 10, 0, 2, 0, 48, 7, 0, 49, 10, 0, 4, 0, 50, 7, 0, 51, 7, 0, 52, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0, 18, 76, 111, 99, 97, 108, 86, 97, 114, 105, 97, 98, 108, 101, 84, 97, 98, 108, 101, 1, 0, 4, 116, 104, 105, 115, 1, 0, 42, 76, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 67, 111, 110, 102, 105, 103, 59, 1, 0, 16, 115, 104, 117, 116, 100, 111, 119, 110, 76, 105, 115, 116, 101, 110, 101, 114, 1, 0, 103, 40, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 69, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 59, 41, 76, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 104, 101, 97, 108, 116, 104, 47, 83, 104, 117, 116, 100, 111, 119, 110, 76, 105, 115, 116, 101, 110, 101, 114, 59, 1, 0, 25, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 69, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 1, 0, 55, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 69, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 59, 1, 0, 16, 77, 101, 116, 104, 111, 100, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 1, 0, 25, 82, 117, 110, 116, 105, 109, 101, 86, 105, 115, 105, 98, 108, 101, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 115, 1, 0, 45, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 47, 66, 101, 97, 110, 59, 1, 0, 11, 115, 116, 97, 116, 101, 76, 111, 103, 103, 101, 114, 1, 1, 44, 40, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 69, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 59, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 69, 110, 100, 112, 111, 105, 110, 116, 71, 114, 111, 117, 112, 115, 59, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 82, 101, 103, 105, 115, 116, 114, 121, 59, 76, 106, 97, 118, 97, 47, 116, 105, 109, 101, 47, 68, 117, 114, 97, 116, 105, 111, 110, 59, 76, 105, 111, 47, 109, 105, 99, 114, 111, 109, 101, 116, 101, 114, 47, 99, 111, 114, 101, 47, 105, 110, 115, 116, 114, 117, 109, 101, 110, 116, 47, 77, 101, 116, 101, 114, 82, 101, 103, 105, 115, 116, 114, 121, 59, 41, 76, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 71, 114, 111, 117, 112, 83, 116, 97, 116, 117, 115, 78, 111, 116, 105, 102, 105, 101, 114, 59, 1, 0, 14, 101, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 1, 0, 20, 104, 101, 97, 108, 116, 104, 69, 110, 100, 112, 111, 105, 110, 116, 71, 114, 111, 117, 112, 115, 1, 0, 62, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 69, 110, 100, 112, 111, 105, 110, 116, 71, 114, 111, 117, 112, 115, 59, 1, 0, 25, 104, 101, 97, 108, 116, 104, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 82, 101, 103, 105, 115, 116, 114, 121, 1, 0, 61, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 82, 101, 103, 105, 115, 116, 114, 121, 59, 1, 0, 10, 99, 104, 101, 99, 107, 68, 101, 108, 97, 121, 1, 0, 20, 76, 106, 97, 118, 97, 47, 116, 105, 109, 101, 47, 68, 117, 114, 97, 116, 105, 111, 110, 59, 1, 0, 13, 109, 101, 116, 101, 114, 82, 101, 103, 105, 115, 116, 114, 121, 1, 0, 45, 76, 105, 111, 47, 109, 105, 99, 114, 111, 109, 101, 116, 101, 114, 47, 99, 111, 114, 101, 47, 105, 110, 115, 116, 114, 117, 109, 101, 110, 116, 47, 77, 101, 116, 101, 114, 82, 101, 103, 105, 115, 116, 114, 121, 59, 1, 0, 22, 76, 111, 99, 97, 108, 86, 97, 114, 105, 97, 98, 108, 101, 84, 121, 112, 101, 84, 97, 98, 108, 101, 1, 0, 122, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 82, 101, 103, 105, 115, 116, 114, 121, 60, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 59, 62, 59, 1, 0, 9, 83, 105, 103, 110, 97, 116, 117, 114, 101, 1, 1, 105, 40, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 69, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 59, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 69, 110, 100, 112, 111, 105, 110, 116, 71, 114, 111, 117, 112, 115, 59, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 82, 101, 103, 105, 115, 116, 114, 121, 60, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 59, 62, 59, 76, 106, 97, 118, 97, 47, 116, 105, 109, 101, 47, 68, 117, 114, 97, 116, 105, 111, 110, 59, 76, 105, 111, 47, 109, 105, 99, 114, 111, 109, 101, 116, 101, 114, 47, 99, 111, 114, 101, 47, 105, 110, 115, 116, 114, 117, 109, 101, 110, 116, 47, 77, 101, 116, 101, 114, 82, 101, 103, 105, 115, 116, 114, 121, 59, 41, 76, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 71, 114, 111, 117, 112, 83, 116, 97, 116, 117, 115, 78, 111, 116, 105, 102, 105, 101, 114, 59, 1, 0, 34, 82, 117, 110, 116, 105, 109, 101, 86, 105, 115, 105, 98, 108, 101, 80, 97, 114, 97, 109, 101, 116, 101, 114, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 115, 1, 0, 52, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 101, 97, 110, 115, 47, 102, 97, 99, 116, 111, 114, 121, 47, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 47, 86, 97, 108, 117, 101, 59, 1, 0, 5, 118, 97, 108, 117, 101, 1, 0, 109, 36, 123, 104, 101, 97, 108, 116, 104, 45, 103, 114, 111, 117, 112, 45, 110, 111, 116, 105, 102, 105, 101, 114, 46, 99, 104, 101, 99, 107, 45, 100, 101, 108, 97, 121, 58, 35, 123, 84, 40, 106, 97, 118, 97, 46, 116, 105, 109, 101, 46, 68, 117, 114, 97, 116, 105, 111, 110, 41, 46, 111, 102, 40, 50, 44, 32, 84, 40, 106, 97, 118, 97, 46, 116, 105, 109, 101, 46, 116, 101, 109, 112, 111, 114, 97, 108, 46, 67, 104, 114, 111, 110, 111, 85, 110, 105, 116, 41, 46, 83, 69, 67, 79, 78, 68, 83, 41, 125, 125, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1, 0, 17, 72, 101, 97, 108, 116, 104, 67, 111, 110, 102, 105, 103, 46, 106, 97, 118, 97, 1, 0, 54, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 47, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 59, 1, 0, 27, 82, 117, 110, 116, 105, 109, 101, 73, 110, 118, 105, 115, 105, 98, 108, 101, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 115, 1, 0, 51, 76, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 78, 111, 116, 71, 101, 110, 101, 114, 97, 116, 101, 100, 66, 117, 116, 74, 97, 99, 111, 99, 111, 73, 103, 110, 111, 114, 101, 100, 59, 12, 0, 8, 0, 9, 1, 0, 44, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 104, 101, 97, 108, 116, 104, 47, 83, 104, 117, 116, 100, 111, 119, 110, 76, 105, 115, 116, 101, 110, 101, 114, 12, 0, 8, 0, 53, 1, 0, 53, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 71, 114, 111, 117, 112, 83, 116, 97, 116, 117, 115, 78, 111, 116, 105, 102, 105, 101, 114, 12, 0, 8, 0, 54, 1, 0, 40, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 67, 111, 110, 102, 105, 103, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0, 58, 40, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 69, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 59, 41, 86, 1, 0, -10, 40, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 69, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 59, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 69, 110, 100, 112, 111, 105, 110, 116, 71, 114, 111, 117, 112, 115, 59, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 82, 101, 103, 105, 115, 116, 114, 121, 59, 76, 105, 111, 47, 109, 105, 99, 114, 111, 109, 101, 116, 101, 114, 47, 99, 111, 114, 101, 47, 105, 110, 115, 116, 114, 117, 109, 101, 110, 116, 47, 77, 101, 116, 101, 114, 82, 101, 103, 105, 115, 116, 114, 121, 59, 76, 106, 97, 118, 97, 47, 116, 105, 109, 101, 47, 68, 117, 114, 97, 116, 105, 111, 110, 59, 41, 86, 0, 33, 0, 6, 0, 7, 0, 0, 0, 0, 0, 3, 0, 1, 0, 8, 0, 9, 0, 1, 0, 10, 0, 0, 0, 47, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0, 1, -79, 0, 0, 0, 2, 0, 11, 0, 0, 0, 6, 0, 1, 0, 0, 0, 21, 0, 12, 0, 0, 0, 12, 0, 1, 0, 0, 0, 5, 0, 13, 0, 14, 0, 0, 0, 0, 0, 15, 0, 16, 0, 3, 0, 10, 0, 0, 0, 61, 0, 3, 0, 2, 0, 0, 0, 9, -69, 0, 2, 89, 43, -73, 0, 3, -80, 0, 0, 0, 2, 0, 11, 0, 0, 0, 6, 0, 1, 0, 0, 0, 25, 0, 12, 0, 0, 0, 22, 0, 2, 0, 0, 0, 9, 0, 13, 0, 14, 0, 0, 0, 0, 0, 9, 0, 17, 0, 18, 0, 1, 0, 19, 0, 0, 0, 5, 1, 0, 17, 0, 0, 0, 20, 0, 0, 0, 6, 0, 1, 0, 21, 0, 0, 0, 0, 0, 22, 0, 23, 0, 5, 0, 10, 0, 0, 0, 125, 0, 7, 0, 6, 0, 0, 0, 15, -69, 0, 4, 89, 43, 44, 45, 25, 5, 25, 4, -73, 0, 5, -80, 0, 0, 0, 3, 0, 11, 0, 0, 0, 6, 0, 1, 0, 0, 0, 36, 0, 12, 0, 0, 0, 62, 0, 6, 0, 0, 0, 15, 0, 13, 0, 14, 0, 0, 0, 0, 0, 15, 0, 24, 0, 18, 0, 1, 0, 0, 0, 15, 0, 25, 0, 26, 0, 2, 0, 0, 0, 15, 0, 27, 0, 28, 0, 3, 0, 0, 0, 15, 0, 29, 0, 30, 0, 4, 0, 0, 0, 15, 0, 31, 0, 32, 0, 5, 0, 33, 0, 0, 0, 12, 0, 1, 0, 0, 0, 15, 0, 27, 0, 34, 0, 3, 0, 19, 0, 0, 0, 21, 5, 0, 24, 0, 0, 0, 25, 0, 0, 0, 27, 0, 0, 0, 29, 0, 0, 0, 31, 0, 0, 0, 35, 0, 0, 0, 2, 0, 36, 0, 20, 0, 0, 0, 6, 0, 1, 0, 21, 0, 0, 0, 37, 0, 0, 0, 20, 5, 0, 0, 0, 0, 0, 0, 0, 1, 0, 38, 0, 1, 0, 39, 115, 0, 40, 0, 0, 0, 3, 0, 41, 0, 0, 0, 2, 0, 42, 0, 20, 0, 0, 0, 6, 0, 1, 0, 43, 0, 0, 0, 44, 0, 0, 0, 6, 0, 1, 0, 45, 0, 0]
outputStream.toByteArray(): [-54, -2, -70, -66, 0, 0, 0, 55, 0, 55, 10, 0, 7, 0, 46, 7, 0, 47, 10, 0, 2, 0, 48, 7, 0, 49, 10, 0, 4, 0, 50, 7, 0, 51, 7, 0, 52, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0, 18, 76, 111, 99, 97, 108, 86, 97, 114, 105, 97, 98, 108, 101, 84, 97, 98, 108, 101, 1, 0, 4, 116, 104, 105, 115, 1, 0, 42, 76, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 67, 111, 110, 102, 105, 103, 59, 1, 0, 16, 115, 104, 117, 116, 100, 111, 119, 110, 76, 105, 115, 116, 101, 110, 101, 114, 1, 0, 103, 40, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 69, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 59, 41, 76, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 104, 101, 97, 108, 116, 104, 47, 83, 104, 117, 116, 100, 111, 119, 110, 76, 105, 115, 116, 101, 110, 101, 114, 59, 1, 0, 25, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 69, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 1, 0, 55, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 69, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 59, 1, 0, 16, 77, 101, 116, 104, 111, 100, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 1, 0, 25, 82, 117, 110, 116, 105, 109, 101, 86, 105, 115, 105, 98, 108, 101, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 115, 1, 0, 45, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 47, 66, 101, 97, 110, 59, 1, 0, 11, 115, 116, 97, 116, 101, 76, 111, 103, 103, 101, 114, 1, 1, 44, 40, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 69, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 59, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 69, 110, 100, 112, 111, 105, 110, 116, 71, 114, 111, 117, 112, 115, 59, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 82, 101, 103, 105, 115, 116, 114, 121, 59, 76, 106, 97, 118, 97, 47, 116, 105, 109, 101, 47, 68, 117, 114, 97, 116, 105, 111, 110, 59, 76, 105, 111, 47, 109, 105, 99, 114, 111, 109, 101, 116, 101, 114, 47, 99, 111, 114, 101, 47, 105, 110, 115, 116, 114, 117, 109, 101, 110, 116, 47, 77, 101, 116, 101, 114, 82, 101, 103, 105, 115, 116, 114, 121, 59, 41, 76, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 71, 114, 111, 117, 112, 83, 116, 97, 116, 117, 115, 78, 111, 116, 105, 102, 105, 101, 114, 59, 1, 0, 14, 101, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 1, 0, 20, 104, 101, 97, 108, 116, 104, 69, 110, 100, 112, 111, 105, 110, 116, 71, 114, 111, 117, 112, 115, 1, 0, 62, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 69, 110, 100, 112, 111, 105, 110, 116, 71, 114, 111, 117, 112, 115, 59, 1, 0, 25, 104, 101, 97, 108, 116, 104, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 82, 101, 103, 105, 115, 116, 114, 121, 1, 0, 61, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 82, 101, 103, 105, 115, 116, 114, 121, 59, 1, 0, 10, 99, 104, 101, 99, 107, 68, 101, 108, 97, 121, 1, 0, 20, 76, 106, 97, 118, 97, 47, 116, 105, 109, 101, 47, 68, 117, 114, 97, 116, 105, 111, 110, 59, 1, 0, 13, 109, 101, 116, 101, 114, 82, 101, 103, 105, 115, 116, 114, 121, 1, 0, 45, 76, 105, 111, 47, 109, 105, 99, 114, 111, 109, 101, 116, 101, 114, 47, 99, 111, 114, 101, 47, 105, 110, 115, 116, 114, 117, 109, 101, 110, 116, 47, 77, 101, 116, 101, 114, 82, 101, 103, 105, 115, 116, 114, 121, 59, 1, 0, 22, 76, 111, 99, 97, 108, 86, 97, 114, 105, 97, 98, 108, 101, 84, 121, 112, 101, 84, 97, 98, 108, 101, 1, 0, 122, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 82, 101, 103, 105, 115, 116, 114, 121, 60, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 59, 62, 59, 1, 0, 9, 83, 105, 103, 110, 97, 116, 117, 114, 101, 1, 1, 105, 40, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 69, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 59, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 69, 110, 100, 112, 111, 105, 110, 116, 71, 114, 111, 117, 112, 115, 59, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 82, 101, 103, 105, 115, 116, 114, 121, 60, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 59, 62, 59, 76, 106, 97, 118, 97, 47, 116, 105, 109, 101, 47, 68, 117, 114, 97, 116, 105, 111, 110, 59, 76, 105, 111, 47, 109, 105, 99, 114, 111, 109, 101, 116, 101, 114, 47, 99, 111, 114, 101, 47, 105, 110, 115, 116, 114, 117, 109, 101, 110, 116, 47, 77, 101, 116, 101, 114, 82, 101, 103, 105, 115, 116, 114, 121, 59, 41, 76, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 71, 114, 111, 117, 112, 83, 116, 97, 116, 117, 115, 78, 111, 116, 105, 102, 105, 101, 114, 59, 1, 0, 34, 82, 117, 110, 116, 105, 109, 101, 86, 105, 115, 105, 98, 108, 101, 80, 97, 114, 97, 109, 101, 116, 101, 114, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 115, 1, 0, 52, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 101, 97, 110, 115, 47, 102, 97, 99, 116, 111, 114, 121, 47, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 47, 86, 97, 108, 117, 101, 59, 1, 0, 5, 118, 97, 108, 117, 101, 1, 0, 109, 36, 123, 104, 101, 97, 108, 116, 104, 45, 103, 114, 111, 117, 112, 45, 110, 111, 116, 105, 102, 105, 101, 114, 46, 99, 104, 101, 99, 107, 45, 100, 101, 108, 97, 121, 58, 35, 123, 84, 40, 106, 97, 118, 97, 46, 116, 105, 109, 101, 46, 68, 117, 114, 97, 116, 105, 111, 110, 41, 46, 111, 102, 40, 50, 44, 32, 84, 40, 106, 97, 118, 97, 46, 116, 105, 109, 101, 46, 116, 101, 109, 112, 111, 114, 97, 108, 46, 67, 104, 114, 111, 110, 111, 85, 110, 105, 116, 41, 46, 83, 69, 67, 79, 78, 68, 83, 41, 125, 125, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1, 0, 17, 72, 101, 97, 108, 116, 104, 67, 111, 110, 102, 105, 103, 46, 106, 97, 118, 97, 1, 0, 54, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 47, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 59, 1, 0, 27, 82, 117, 110, 116, 105, 109, 101, 73, 110, 118, 105, 115, 105, 98, 108, 101, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 115, 1, 0, 51, 76, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 78, 111, 116, 71, 101, 110, 101, 114, 97, 116, 101, 100, 66, 117, 116, 74, 97, 99, 111, 99, 111, 73, 103, 110, 111, 114, 101, 100, 59, 12, 0, 8, 0, 9, 1, 0, 44, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 104, 101, 97, 108, 116, 104, 47, 83, 104, 117, 116, 100, 111, 119, 110, 76, 105, 115, 116, 101, 110, 101, 114, 12, 0, 8, 0, 53, 1, 0, 53, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 71, 114, 111, 117, 112, 83, 116, 97, 116, 117, 115, 78, 111, 116, 105, 102, 105, 101, 114, 12, 0, 8, 0, 54, 1, 0, 40, 99, 111, 109, 47, 116, 111, 109, 116, 111, 109, 47, 108, 110, 115, 47, 98, 97, 116, 99, 104, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 67, 111, 110, 102, 105, 103, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0, 58, 40, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 69, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 59, 41, 86, 1, 0, -10, 40, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 99, 111, 110, 116, 101, 120, 116, 47, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 69, 118, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 101, 114, 59, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 72, 101, 97, 108, 116, 104, 69, 110, 100, 112, 111, 105, 110, 116, 71, 114, 111, 117, 112, 115, 59, 76, 111, 114, 103, 47, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 47, 98, 111, 111, 116, 47, 97, 99, 116, 117, 97, 116, 101, 47, 104, 101, 97, 108, 116, 104, 47, 67, 111, 110, 116, 114, 105, 98, 117, 116, 111, 114, 82, 101, 103, 105, 115, 116, 114, 121, 59, 76, 105, 111, 47, 109, 105, 99, 114, 111, 109, 101, 116, 101, 114, 47, 99, 111, 114, 101, 47, 105, 110, 115, 116, 114, 117, 109, 101, 110, 116, 47, 77, 101, 116, 101, 114, 82, 101, 103, 105, 115, 116, 114, 121, 59, 76, 106, 97, 118, 97, 47, 116, 105, 109, 101, 47, 68, 117, 114, 97, 116, 105, 111, 110, 59, 41, 86, 0, 33, 0, 6, 0, 7, 0, 0, 0, 0, 0, 3, 0, 1, 0, 8, 0, 9, 0, 1, 0, 10, 0, 0, 0, 47, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0, 1, -79, 0, 0, 0, 2, 0, 11, 0, 0, 0, 6, 0, 1, 0, 0, 0, 21, 0, 12, 0, 0, 0, 12, 0, 1, 0, 0, 0, 5, 0, 13, 0, 14, 0, 0, 0, 0, 0, 15, 0, 16, 0, 3, 0, 10, 0, 0, 0, 61, 0, 3, 0, 2, 0, 0, 0, 9, -69, 0, 2, 89, 43, -73, 0, 3, -80, 0, 0, 0, 2, 0, 11, 0, 0, 0, 6, 0, 1, 0, 0, 0, 25, 0, 12, 0, 0, 0, 22, 0, 2, 0, 0, 0, 9, 0, 13, 0, 14, 0, 0, 0, 0, 0, 9, 0, 17, 0, 18, 0, 1, 0, 19, 0, 0, 0, 5, 1, 0, 17, 0, 0, 0, 20, 0, 0, 0, 6, 0, 1, 0, 21, 0, 0, 0, 0, 0, 22, 0, 23, 0, 5, 0, 10, 0, 0, 0, 125, 0, 7, 0, 6, 0, 0, 0, 15, -69, 0, 4, 89, 43, 44, 45, 25, 5, 25, 4, -73, 0, 5, -80, 0, 0, 0, 3, 0, 11, 0, 0, 0, 6, 0, 1, 0, 0, 0, 36, 0, 12, 0, 0, 0, 62, 0, 6, 0, 0, 0, 15, 0, 13, 0, 14, 0, 0, 0, 0, 0, 15, 0, 24, 0, 18, 0, 1, 0, 0, 0, 15, 0, 25, 0, 26, 0, 2, 0, 0, 0, 15, 0, 27, 0, 28, 0, 3, 0, 0, 0, 15, 0, 29, 0, 30, 0, 4, 0, 0, 0, 15, 0, 31, 0, 32, 0, 5, 0, 33, 0, 0, 0, 12, 0, 1, 0, 0, 0, 15, 0, 27, 0, 34, 0, 3, 0, 19, 0, 0, 0, 21, 5, 0, 24, 0, 0, 0, 25, 0, 0, 0, 27, 0, 0, 0, 29, 0, 0, 0, 31, 0, 0, 0, 35, 0, 0, 0, 2, 0, 36, 0, 20, 0, 0, 0, 6, 0, 1, 0, 21, 0, 0, 0, 37, 0, 0, 0, 20, 5, 0, 0, 0, 0, 0, 0, 0, 1, 0, 38, 0, 1, 0, 39, 115, 0, 40, 0, 0, 0, 3, 0, 41, 0, 0, 0, 2, 0, 42, 0, 20, 0, 0, 0, 6, 0, 1, 0, 43, 0, 0, 0, 44, 0, 0, 0, 6, 0, 1, 0, 45, 0, 0]
==========================

Here I see, that buffer data differs from outputStream.toByteArray() result.
When I remove following optimization, spring loads class correctly:

      if (readCount == 1) {
        return data;
      }

@MichalKoziorowski-TomTom
Copy link
Author

Hi @jhoeller

Could you look at this issue? It was introduced in commit d29d4d4

@bclozel
Copy link
Member

bclozel commented Sep 17, 2021

@MichalKoziorowski-TomTom Spring Framework is tracking changes on the official ASM repository.
Is there a way to reproduce this issue in a sample github repository? If so, we could raise this issue with the ASM team.

@bclozel bclozel added the status: waiting-for-feedback We need additional information before we can continue label Sep 17, 2021
@MichalKoziorowski-TomTom
Copy link
Author

Hi @bclozel

The more I try to reproduce this issue locally, the more I think it is somewhere in my JDK / linux distribution, not in Spring / ASM.

I've tried to reproduce it on my local machine using trivial code in which I read same class from same JAR:

    DefaultResourceLoader defaultResourceLoader = new DefaultResourceLoader();
    Resource resource = defaultResourceLoader.getResource(
        "jar:file:/home/koziorow/shared-1.0-SNAPSHOT.jar!/com/tomtom/lns/batch/health/HealthConfig.class");
    InputStream inputStream = resource.getInputStream();
    ClassReader classReader = new ClassReader(inputStream);

On my local machine it this always works. I will try next week to run this in the same docker environment where
project is normally running.

For me, it looks like last call to inputStream.read(data, 0, bufferSize)), which returns -1 somehow modifies data buffer. I'm not sure if it's legal for input stream to modify data buffer in such case.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Sep 17, 2021
@bclozel
Copy link
Member

bclozel commented Sep 17, 2021

This sounds like a "fun" issue to track down - I'll leave this issue opened, waiting for your feedback.
Thanks!

@bclozel bclozel added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Sep 17, 2021
@180254
Copy link

180254 commented Sep 17, 2021

I worked with Michal to analyze this problem. We managed to reproduce the problem and determine the minimum necessary environment.

The environment we use uses the cloudflare's zlib fork (https://github.com/cloudflare/zlib).
As long as uses zlib distributed with a system, everything is fine.
The problem appears when uses the mentioned zlib fork.

We have created a sample github repository that easily reproduces the problem.
https://github.com/180254/spring-framework-issue-27429

Reproduction steps:
$ ./0-run-on-common-env.sh - it works.
$ ./1-run-on-zlib-cloudflare-env-and-spring-framework-ver-5.3.7.sh - it works.
$ ./2-run-on-zlib-cloudflare-env-and-spring-framework-ver-5.3.10.sh - it does not work. The error message is like in the first post.

We were also able to confirm supposition that last call to inputStream.read(data, 0, bufferSize)) returns -1 and modifies data buffer, To see the proof, run:
$ ./3-run-classreader2-on-common-env.sh - the buffer was not modified in the last pass of the loop.
$ ./4-run-classreader2-on-zlib-cloudflare-env-and-spring-framework-ver-5.3.10.sh - the buffer was modified in the last pass of the loop.

So the problem appears on a custom environment. However it seems to me, that cloudflare's zlib fork is so good and popular, that it is worth to take this problem and continue compatibility with spring boot.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Sep 17, 2021
@jhoeller jhoeller changed the title spring framework >= 3.5.8 ASM ClassReader failed to parse class file - probably due to a new ... Unsupported class file major version 21845 spring framework >= 5.3.8 ASM ClassReader failed to parse class file - probably due to a new ... Unsupported class file major version 21845 Sep 17, 2021
@jhoeller jhoeller changed the title spring framework >= 5.3.8 ASM ClassReader failed to parse class file - probably due to a new ... Unsupported class file major version 21845 Spring Framework >= 5.3.8 ASM ClassReader fails to parse class file due to InputStream optimization Sep 17, 2021
@jhoeller
Copy link
Contributor

jhoeller commented Sep 17, 2021

The InputStream handling optimization seems to be linked to this original ASM commit: https://gitlab.ow2.org/asm/asm/-/commit/cfda364ce57e39412b6cc89699b1003c6da6ec41 - making it not only into our ASM fork but also into ASM 9.2 proper. From that perspective, you should talk the issue to the ASM project itself; we'll track the outcome there.

That said, this does look like a misbehaving InputStream implementation to me. A -1 return value there signals no further data read into the buffer, otherwise a positive return value would indicate the actual number of bytes read in that particular attempt. It is meant to be a safe assumption on the caller's side to not even look at the buffer in case of a -1 return value.

For a quick fix, we can remove the optimization in our ASM fork in Spring Framework 5.3.11. It just seems like a workaround for a bug in that particular InputStream implementation...

@jhoeller jhoeller self-assigned this Sep 17, 2021
@jhoeller jhoeller added in: core Issues in core modules (aop, beans, core, context, expression) type: regression A bug that is also a regression and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Sep 17, 2021
@jhoeller jhoeller added this to the 5.3.11 milestone Sep 17, 2021
@MichalKoziorowski-TomTom
Copy link
Author

Hi.

We will report this also in ASM project, but temporary removing this optimization would be nice to have. I'm not sure how long it will take until problem in Java sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream or in Cloudflare zlib implementation will be found.

@180254
Copy link

180254 commented Sep 18, 2021

I have created an issue in the ASM issues tracker: https://gitlab.ow2.org/asm/asm/-/issues/317955

@bclozel
Copy link
Member

bclozel commented Sep 20, 2021

@MichalKoziorowski-TomTom @180254 It looks like the issue got closed on the ASM side. We agree that the InputStream implementation is here faulty and goes against the contract.

We're willing to reverse this optimization for the next version - until this situation is properly handled in CloudFlare's zlib. Did you report this issue to the library maintainers? Could you share the link here? Thanks!

@MichalKoziorowski-TomTom
Copy link
Author

I would love to create issue in CloudFlare zlib (https://github.com/cloudflare/zlib), but they don't seem to have issues tab :( Also no contact information. I think we will try to contact one of the commiters. Maybe we will be lucky :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: feedback-provided Feedback has been provided type: regression A bug that is also a regression
Projects
None yet
Development

No branches or pull requests

5 participants