This is an automated email from the ASF dual-hosted git repository.

samt pushed a commit to branch cassandra-4.1
in repository https://gitbox.apache.org/repos/asf/cassandra.git

commit 28759d8bbc16daf45ca07ee27b4a8dfedc8cf92b
Author: David Capwell <[email protected]>
AuthorDate: Tue Dec 13 13:37:40 2022 -0800

    CEP-10: Simulator Java11 Support (backport to cassandra-4.1)
    
    patch by David Capwell; reviewed by Benedict Elliott Smith, Ekaterina 
Dimitrova for CASSANDRA-17178
    backported to 4.1 in CASSANDRA-19935
---
 CHANGES.txt                                        |  1 +
 .../cassandra/simulator/asm/ClassTransformer.java  | 51 +++++++++++++++++++++-
 .../cassandra/simulator/asm/InterceptAgent.java    |  6 ++-
 .../cassandra/simulator/asm/InterceptClasses.java  |  1 +
 .../org/apache/cassandra/simulator/asm/Utils.java  |  8 ++++
 5 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index 6d6da13c10..bcb9dec299 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 4.1.8
+ * Backport Java 11 support for Simulator (CASSANDRA-17178/CASSANDRA-19935)
  * Equality check for Paxos.Electorate should not depend on collection types 
(CASSANDRA-19935)
  * Fix race condition in DecayingEstimatedHistogramReservoir during rescale 
(CASSANDRA-19365)
 Merged from 4.0:
diff --git 
a/test/simulator/asm/org/apache/cassandra/simulator/asm/ClassTransformer.java 
b/test/simulator/asm/org/apache/cassandra/simulator/asm/ClassTransformer.java
index 6e6b0d30de..778e44c808 100644
--- 
a/test/simulator/asm/org/apache/cassandra/simulator/asm/ClassTransformer.java
+++ 
b/test/simulator/asm/org/apache/cassandra/simulator/asm/ClassTransformer.java
@@ -110,6 +110,8 @@ class ClassTransformer extends ClassVisitor implements 
MethodWriterSink
     private final EnumSet<Flag> flags;
     private final Consumer<String> dependentTypes;
 
+    private boolean updateVisibility = false;
+
     ClassTransformer(int api, String className, EnumSet<Flag> flags, 
Consumer<String> dependentTypes)
     {
         this(api, new ClassWriter(0), className, flags, null, null, null, 
null, dependentTypes);
@@ -137,12 +139,58 @@ class ClassTransformer extends ClassVisitor implements 
MethodWriterSink
         this.methodLogger = MethodLogger.log(api, className);
     }
 
+    public void setUpdateVisibility(boolean updateVisibility)
+    {
+        this.updateVisibility = updateVisibility;
+    }
+
+    /**
+     * Java 11 changed the way that classes defined in the same source file 
get access to private state (see https://openjdk.org/jeps/181),
+     * rather than trying to adapt to this, this method attempts to make the 
field/method/class public so that access
+     * is not restricted.
+     */
+    private int makePublic(int access)
+    {
+        if (!updateVisibility)
+            return access;
+        // leave non-user created methods/fields/etc. alone
+        if (contains(access, Opcodes.ACC_BRIDGE) || contains(access, 
Opcodes.ACC_SYNTHETIC))
+            return access;
+        if (contains(access, Opcodes.ACC_PRIVATE))
+        {
+            access &= ~Opcodes.ACC_PRIVATE;
+            access |= Opcodes.ACC_PUBLIC;
+        }
+        else if (contains(access, Opcodes.ACC_PROTECTED))
+        {
+            access &= ~Opcodes.ACC_PROTECTED;
+            access |= Opcodes.ACC_PUBLIC;
+        }
+        else if (!contains(access, Opcodes.ACC_PUBLIC)) // package-protected
+        {
+            access |= Opcodes.ACC_PUBLIC;
+        }
+        return access;
+    }
+
+    private static boolean contains(int value, int mask)
+    {
+        return (value & mask) != 0;
+    }
+
+    @Override
+    public void visit(int version, int access, String name, String signature, 
String superName, String[] interfaces)
+    {
+        super.visit(version, makePublic(access), name, signature, superName, 
interfaces);
+
+    }
+
     @Override
     public FieldVisitor visitField(int access, String name, String descriptor, 
String signature, Object value)
     {
         if (dependentTypes != null)
             Utils.visitIfRefType(descriptor, dependentTypes);
-        return super.visitField(access, name, descriptor, signature, value);
+        return super.visitField(makePublic(access), name, descriptor, 
signature, value);
     }
 
     @Override
@@ -176,6 +224,7 @@ class ClassTransformer extends ClassVisitor implements 
MethodWriterSink
             isToString = true;
         }
 
+        access = makePublic(access);
         MethodVisitor visitor;
         if (flags.contains(MONITORS) && (access & Opcodes.ACC_SYNCHRONIZED) != 
0)
         {
diff --git 
a/test/simulator/asm/org/apache/cassandra/simulator/asm/InterceptAgent.java 
b/test/simulator/asm/org/apache/cassandra/simulator/asm/InterceptAgent.java
index 87cfab0f6f..ffa9b180e5 100644
--- a/test/simulator/asm/org/apache/cassandra/simulator/asm/InterceptAgent.java
+++ b/test/simulator/asm/org/apache/cassandra/simulator/asm/InterceptAgent.java
@@ -296,12 +296,14 @@ public class InterceptAgent
                     visitor.visitMethodInsn(INVOKESTATIC, "java/lang/Thread", 
"currentThread", "()Ljava/lang/Thread;", false);
                     visitor.visitFieldInsn(GETSTATIC, 
"java/util/concurrent/ThreadLocalRandom", "SEED", "J");
                     visitor.visitMethodInsn(INVOKESTATIC, 
"org/apache/cassandra/simulator/systems/InterceptorOfSystemMethods$Global", 
"randomSeed", "()J", false);
-                    visitor.visitMethodInsn(INVOKEVIRTUAL, "sun/misc/Unsafe", 
"putLong", "(Ljava/lang/Object;JJ)V", false);
+
+                    String unsafeClass = 
Utils.descriptorToClassName(unsafeDescriptor);
+                    visitor.visitMethodInsn(INVOKEVIRTUAL, unsafeClass, 
"putLong", "(Ljava/lang/Object;JJ)V", false);
                     visitor.visitFieldInsn(GETSTATIC, 
"java/util/concurrent/ThreadLocalRandom", unsafeFieldName, unsafeDescriptor);
                     visitor.visitMethodInsn(INVOKESTATIC, "java/lang/Thread", 
"currentThread", "()Ljava/lang/Thread;", false);
                     visitor.visitFieldInsn(GETSTATIC, 
"java/util/concurrent/ThreadLocalRandom", "PROBE", "J");
                     visitor.visitLdcInsn(0);
-                    visitor.visitMethodInsn(INVOKEVIRTUAL, "sun/misc/Unsafe", 
"putInt", "(Ljava/lang/Object;JI)V", false);
+                    visitor.visitMethodInsn(INVOKEVIRTUAL, unsafeClass, 
"putInt", "(Ljava/lang/Object;JI)V", false);
                     visitor.visitInsn(RETURN);
                     visitor.visitLabel(new Label());
                     visitor.visitMaxs(6, 1);
diff --git 
a/test/simulator/asm/org/apache/cassandra/simulator/asm/InterceptClasses.java 
b/test/simulator/asm/org/apache/cassandra/simulator/asm/InterceptClasses.java
index a57074db27..473cc27032 100644
--- 
a/test/simulator/asm/org/apache/cassandra/simulator/asm/InterceptClasses.java
+++ 
b/test/simulator/asm/org/apache/cassandra/simulator/asm/InterceptClasses.java
@@ -246,6 +246,7 @@ public class InterceptClasses implements BiFunction<String, 
byte[], byte[]>
         }
 
         ClassTransformer transformer = new ClassTransformer(api, internalName, 
flags, monitorDelayChance, new NemesisGenerator(api, internalName, 
nemesisChance), nemesisFieldSelector, hashcode, dependentTypes);
+        transformer.setUpdateVisibility(true);
         transformer.readAndTransform(input);
 
         if (!transformer.isTransformed())
diff --git a/test/simulator/asm/org/apache/cassandra/simulator/asm/Utils.java 
b/test/simulator/asm/org/apache/cassandra/simulator/asm/Utils.java
index be2ef6c5d8..d710ffe417 100644
--- a/test/simulator/asm/org/apache/cassandra/simulator/asm/Utils.java
+++ b/test/simulator/asm/org/apache/cassandra/simulator/asm/Utils.java
@@ -287,4 +287,12 @@ public class Utils
                 forEach.accept(descriptor.substring(i + 1, descriptor.length() 
- 1));
         }
     }
+
+    public static String descriptorToClassName(String desc)
+    {
+        // samples: "Ljdk/internal/misc/Unsafe;", "Lsun/misc/Unsafe;"
+        if (!(desc.startsWith("L") && desc.endsWith(";")))
+            throw new IllegalArgumentException("Unable to parse descriptor: " 
+ desc);
+        return desc.substring(1, desc.length() - 1);
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to