< prev index next >

src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java

Print this page
@@ -1,7 +1,7 @@
  /*
-  * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
+  * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
   * Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as

@@ -24,30 +24,37 @@
   * questions.
   */
  package jdk.internal.classfile.impl;
  
  import java.lang.classfile.BufWriter;
+ import java.lang.classfile.ClassModel;
  import java.lang.classfile.constantpool.ClassEntry;
  import java.lang.classfile.constantpool.ConstantPool;
  import java.lang.classfile.constantpool.ConstantPoolBuilder;
  import java.lang.classfile.constantpool.PoolEntry;
  import java.util.Arrays;
+ import java.util.HashSet;
  
  import jdk.internal.access.JavaLangAccess;
  import jdk.internal.access.SharedSecrets;
  import jdk.internal.vm.annotation.ForceInline;
  
+ import static java.lang.classfile.ClassFile.ACC_STATIC;
+ import static java.lang.classfile.ClassFile.ACC_STRICT;
  import static java.lang.classfile.constantpool.PoolEntry.TAG_UTF8;
  import static jdk.internal.util.ModifiedUtf.putChar;
  import static jdk.internal.util.ModifiedUtf.utfLen;
  
  public final class BufWriterImpl implements BufWriter {
      private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
  
      private final ConstantPoolBuilder constantPool;
      private final ClassFileImpl context;
      private LabelContext labelContext;
+     private WritableField.UnsetField[] strictInstanceFields; // do not modify array contents
+     private ClassModel lastStrictCheckClass; // buf writer has short life, so do not need weak here
+     private boolean lastStrictCheckResult;
      private final ClassEntry thisClass;
      private final int majorVersion;
      byte[] elems;
      int offset = 0;
  

@@ -65,10 +72,37 @@
          elems = new byte[initialSize];
          this.thisClass = thisClass;
          this.majorVersion = majorVersion;
      }
  
+     public boolean strictFieldsMatch(ClassModel cm) {
+         // We have a cache because this check will be called multiple times
+         // if a MethodModel is sent wholesale
+         if (lastStrictCheckClass == cm) {
+             return lastStrictCheckResult;
+         }
+ 
+         var result = doStrictFieldsMatchCheck(cm);
+         lastStrictCheckClass = cm;
+         lastStrictCheckResult = result;
+         return result;
+     }
+ 
+     private boolean doStrictFieldsMatchCheck(ClassModel cm) {
+         // TODO only check for preview class files?
+         // UTF8 Entry can be used as equality objects
+         var checks = new HashSet<>(Arrays.asList(getStrictInstanceFields()));
+         for (var f : cm.fields()) {
+             if ((f.flags().flagsMask() & (ACC_STATIC | ACC_STRICT)) == ACC_STRICT) {
+                 if (!checks.remove(new WritableField.UnsetField(f.fieldName(), f.fieldType()))) {
+                     return false; // Field mismatch!
+                 }
+             }
+         }
+         return checks.isEmpty();
+     }
+ 
      @Override
      public ConstantPoolBuilder constantPool() {
          return constantPool;
      }
  

@@ -77,10 +111,20 @@
      }
  
      public void setLabelContext(LabelContext labelContext) {
          this.labelContext = labelContext;
      }
+ 
+     public WritableField.UnsetField[] getStrictInstanceFields() {
+         assert strictInstanceFields != null : "should access only after setter call in DirectClassBuilder";
+         return strictInstanceFields;
+     }
+ 
+     public void setStrictInstanceFields(WritableField.UnsetField[] strictInstanceFields) {
+         this.strictInstanceFields = strictInstanceFields;
+     }
+ 
      @Override
      public boolean canWriteDirect(ConstantPool other) {
          return constantPool.canWriteDirect(other);
      }
  
< prev index next >