Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8325522

Some scenarios can cause the JVM to crash when optimizing empty code!

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Incomplete
    • Icon: P3 P3
    • None
    • 8
    • hotspot
    • x86_64
    • os_x

      ADDITIONAL SYSTEM INFORMATION :
      System: Windows10 / Windows11 / Centos6.9 / Centos7.9
      Java Runtime Infomation:The JDK environment we used for testing was JDK1.8u91/JDK1.8u241/JDK1.8u391

      A DESCRIPTION OF THE PROBLEM :
      When the JVM is optimizing partial space code, when certain permutations occur, such as when some code is executed very frequently, it can cause a JVM Crash.
      The crash probability in Windows 10/11 MacOS in JDK1.8u191+181 is very high
      The crash probability in JDK1.8u391 is low and almost impossible to experiment

      Note that we used IDEA's Debug mode to run the code in our tests


      REGRESSION : Last worked in version 8

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Run the test source code directly in Debug mode in IDEA

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Run 5 million cycles normally
      ACTUAL -
      A JVM Crash occurs after tens of thousands of runs

      ---------- BEGIN SOURCE ----------
      Execute the Main method of the current class:
      package org.example.test2;

      import com.hfdp.commons.method.annotation.ParamentValidate;
      import com.hfdp.commons.method.annotation.ValidateRules;

      import java.lang.reflect.Method;
      import java.lang.reflect.Type;
      import java.util.ArrayList;
      import java.util.Date;
      import java.util.HashMap;

      public class TestCrash {
          static class CompileService {
              @ParamentValidate(name = "name")
              @ParamentValidate(index = 1, name = "age")
              public String test01(String name, Integer age) {
                  return "name:" + name + ",age:" + age;
              }
          }

          public static void main(String[] args) {
              CompileService compileService = new CompileService();
              Method method = getMethodByName(compileService.getClass(), true, "test01");

              for (int i = 0; i < 5000000; i++) {
                  Object[] params = new Object[]{"Mr Zhang", 12};
                  Class<?> returnType = method.getReturnType();
                  Class<?>[] parameterTypes = method.getParameterTypes();
                  ParamentValidate[] annotationsByType = method.getAnnotationsByType(ParamentValidate.class);
                  checkParam(params, returnType, annotationsByType, parameterTypes);
                  System.out.println("execute count -> " + i);
              }
          }

          public static Method getMethodByName(Class<?> clazz, boolean ignoreCase, String methodName) throws SecurityException {
              if (null == clazz || "".equals(methodName)) {
                  return null;
              }

              final Method[] methods = clazz.getMethods();
              if (methods != null && methods.length > 0) {
                  for (Method method : methods) {
                      if (equals(methodName, method.getName(), ignoreCase)) {
                          return method;
                      }
                  }
              }
              return null;
          }

          private static void checkParam(Object[] args, Class<?> returnType, ParamentValidate[] paramentValidates, Class[] paramTyps) {
              for (ParamentValidate paramentValidate : paramentValidates) {
                  paramCheck(paramentValidate, paramTyps[paramentValidate.index()], args[paramentValidate.index()]);
              }
          }

          public static String paramCheck(ParamentValidate paramentValidate, Type paramType, Object parn) {
              ValidateRules[] rules = paramentValidate.rules();
              for (ValidateRules rule : rules) {
                  if (checkNull(paramType, parn)) {
                      return paramentValidate.name() + "be not null";
                  }
                  if (rule.equals(ValidateRules.NOT_NULL)) {
                      continue;
                  }
                  if (checkNull(paramType, parn)) {
                      return paramentValidate.name() + "be not null";
                  }
              }
              return null;
          }

          private static boolean checkNull(Type paramType, Object param) {
              boolean typeBl = paramType == String.class || paramType == Integer.class || paramType == Date.class;
              if (typeBl && "".equals(param)) {
                  return true;
              } else {
                  if (paramType.getClass() == Class.class) {
                      if (param instanceof String && "".equals(param)) {
                          return true;
                      }
                      if (param instanceof HashMap) {
                          HashMap value = (HashMap) param;
                          if (value.size() == 0) {
                              return true;
                          }
                      }
                      if (param instanceof ArrayList) {
                          ArrayList value = (ArrayList) param;
                          if (value.size() == 0) {
                              return true;
                          }
                      }
                  }
              }
              return false;
          }

          public static boolean equals(CharSequence str1, CharSequence str2, boolean ignoreCase) {
              if (null == str1) {
                  return str2 == null;
              }
              if (null == str2) {
                  return false;
              }

              if (ignoreCase) {
                  return str1.toString().equalsIgnoreCase(str2.toString());
              } else {
                  return str1.toString().contentEquals(str2);
              }
          }
      }

      Test the classes that need the other two external dependencies in your code:
      @Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD})
      @Retention(RetentionPolicy.RUNTIME)
      @Repeatable(value = ParamentValidates.class)
      public @interface ParamentValidate {

          int index() default 0;

          String name() default "";

          ValidateRules[] rules() default {ValidateRules.NOT_NULL};

          String length() default "";

          int timeOffset() default 0;

          String regularValue() default "";
      }
      public enum ValidateRules {
          NOT_NULL,
          LENGTH,
          NULL_LENGTH,
          MOBILE,
          IDENTITY,
          TIME,
          REGULAR,
          OBJECT;
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      1. On line 67 of TestCrash.java, change rule.equals(ValidateRules.NOT_NULL) to ValidateRules. Not_null.equals (rule)
      2. Upgrade the JDK11 or later version
      3. Set the JVM parameter -Xint

      For now, we'll take the first approach

      FREQUENCY : often


            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: