diff a/test/jdk/java/lang/instrument/RetransformBigClassTest.java b/test/jdk/java/lang/instrument/RetransformBigClassTest.java
--- /dev/null
+++ b/test/jdk/java/lang/instrument/RetransformBigClassTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright Amazon.com Inc. or its affiliates. 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
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @bug 8277444
+ *
+ * @library /test/lib
+ * @compile SimpleIdentityTransformer.java
+ * @run shell MakeJAR.sh retransformAgent
+ * @run main/othervm -javaagent:retransformAgent.jar RetransformBigClassTest
+ */
+
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+/*
+ * JvmtiClassFileReconstituter::copy_bytecodes restores bytecodes rewritten
+ * by the linking process. It is used by RetransformClasses.
+ * JDK-8277444 is a data race between copy_bytecodes and the linking process.
+ * This test puts the linking process in one thread and the retransforming process
+ * in another thread. The test uses Class.forName("BigClass", false, classLoader)
+ * which does not link the class. When the class is used, the linking process starts.
+ * In another thread retransforming of the class is happening.
+ * We generate a class with big methods. A number of methods and their size are
+ * chosen to make the linking and retransforming processes run concurrently.
+ * We delay the retransforming process to follow the linking process.
+ * If there is no synchronization between the processes, a data race will happen.
+ */
+public class RetransformBigClassTest extends AInstrumentationTestCase {
+
+    private static final Object LOCK = new Object();
+    private static final int COUNTER_INC_COUNT            = 2000; // A number of 'c+=1;' statements in methods of a class.
+    private static final int MIN_LINK_TIME_MS             = 60;   // Large enough so the linking and retransforming processes run in parallel.
+    private static final int RETRANSFORM_CLASSES_DELAY_MS = 37;   // We manage to create a data race when a delay is in the range 0.52x - 0.62x of MIN_LINK_TIME_MS.
+
+    private static Class<?> bigClass;
+    private static byte[] bigClassBytecode;
+
+    private Thread retransformThread;
+
+    RetransformBigClassTest() {
+        super("RetransformBigClassTest");
+    }
+
+    public static void main(String[] args) throws Throwable {
+        new RetransformBigClassTest().runTest();
+    }
+
+    protected final void doRunTest() throws Throwable {
+        ClassLoader classLoader = new ClassLoader() {
+                @Override
+                protected Class<?> findClass(String name) throws ClassNotFoundException {
+                    if (name.equals("BigClass")) {
+                        return defineClass(name, bigClassBytecode, 0, bigClassBytecode.length);
+                    }
+
+                    return super.findClass(name);
+                }
+        };
+        synchronized (LOCK) {
+            bigClass = Class.forName("BigClass", false, classLoader);
+            LOCK.notify();
+        }
+        // Make a use of the BigClass
+        assertTrue(bigClass.getConstructor().newInstance().hashCode() != 0);
+        retransformThread.join();
+    }
+
+    private byte[] createClassBytecode(String className, int methodCount) throws Exception {
+        String methodBody = "";
+        for (int j = 0; j < COUNTER_INC_COUNT; j++) {
+            methodBody += "c+=1;";
+        }
+
+        String classSrc = "public class " + className + " { int c;";
+
+        for (int i = 0; i < methodCount; i++) {
+            classSrc += "\npublic void m" + i + "(){";
+            classSrc += methodBody;
+            classSrc += "\n}";
+        }
+        classSrc += "\n}";
+
+        return InMemoryJavaCompiler.compile(className, classSrc);
+    }
+
+    // We need a number of methods such that the linking time is greater than
+    // or equal to MIN_LINK_TIME_MS.
+    // We create a class having 5 methods and trigger the linking process.
+    // We measure the time taken and use it to calculate the needed number.
+    private int findMethodCount() throws Exception {
+        int methodCount = 5;
+        final String className = "BigClass" + methodCount;
+        final byte[] bytecode = createClassBytecode(className, methodCount);
+        ClassLoader classLoader = new ClassLoader() {
+            @Override
+            protected Class<?> findClass(String name) throws ClassNotFoundException {
+                if (name.equals(className)) {
+                    return defineClass(name, bytecode, 0, bytecode.length);
+                }
+
+                return super.findClass(name);
+            }
+        };
+        var bigClass = Class.forName(className, false, classLoader);
+        long startTime = System.nanoTime();
+        assertTrue(bigClass.getConstructor().newInstance().hashCode() != 0);
+        double linkTimeMs = (System.nanoTime() - startTime) / 1000000.0;
+        System.out.println("Link time for a class with " + methodCount + " methods each having " + COUNTER_INC_COUNT + " counter increments: " + Math.round(linkTimeMs));
+        if (linkTimeMs < MIN_LINK_TIME_MS) {
+          methodCount = (int)Math.round((MIN_LINK_TIME_MS * methodCount) / linkTimeMs);
+        }
+        System.out.println("The number of methods to exceed " + MIN_LINK_TIME_MS + " ms linking time: " + methodCount);
+        return methodCount;
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        bigClassBytecode = createClassBytecode("BigClass", findMethodCount());
+        fInst.addTransformer(new SimpleIdentityTransformer());
+        retransformThread = new Thread(() -> {
+            try {
+                synchronized (LOCK) {
+                    while (bigClass == null) {
+                        System.out.println("[retransformThread]: Waiting for bigClass");
+                        LOCK.wait();
+                    }
+                }
+                Thread.sleep(RETRANSFORM_CLASSES_DELAY_MS);
+                fInst.retransformClasses(bigClass);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        });
+        retransformThread.start();
+        Thread.sleep(100);
+    }
+}
