mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
Merge
This commit is contained in:
commit
009f0fb913
8 changed files with 236 additions and 4 deletions
|
@ -777,11 +777,22 @@ bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure) {
|
||||||
// unneeded entries.
|
// unneeded entries.
|
||||||
bool has_redefined_a_class = JvmtiExport::has_redefined_a_class();
|
bool has_redefined_a_class = JvmtiExport::has_redefined_a_class();
|
||||||
MetadataOnStackMark md_on_stack;
|
MetadataOnStackMark md_on_stack;
|
||||||
while (data != NULL) {
|
if (has_redefined_a_class) {
|
||||||
if (data->is_alive(is_alive_closure)) {
|
// purge_previous_versions also cleans weak method links. Because
|
||||||
if (has_redefined_a_class) {
|
// one method's MDO can reference another method from another
|
||||||
|
// class loader, we need to first clean weak method links for all
|
||||||
|
// class loaders here. Below, we can then free redefined methods
|
||||||
|
// for all class loaders.
|
||||||
|
while (data != NULL) {
|
||||||
|
if (data->is_alive(is_alive_closure)) {
|
||||||
data->classes_do(InstanceKlass::purge_previous_versions);
|
data->classes_do(InstanceKlass::purge_previous_versions);
|
||||||
}
|
}
|
||||||
|
data = data->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data = _head;
|
||||||
|
while (data != NULL) {
|
||||||
|
if (data->is_alive(is_alive_closure)) {
|
||||||
data->free_deallocate_list();
|
data->free_deallocate_list();
|
||||||
prev = data;
|
prev = data;
|
||||||
data = data->next();
|
data = data->next();
|
||||||
|
|
|
@ -1556,7 +1556,7 @@ class CleanExtraDataMethodClosure : public CleanExtraDataClosure {
|
||||||
public:
|
public:
|
||||||
CleanExtraDataMethodClosure() {}
|
CleanExtraDataMethodClosure() {}
|
||||||
bool is_live(Method* m) {
|
bool is_live(Method* m) {
|
||||||
return m->on_stack();
|
return !m->is_old() || m->on_stack();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
public class A {
|
||||||
|
void m() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.lang.instrument.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import com.sun.tools.attach.VirtualMachine;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
public class Agent implements ClassFileTransformer {
|
||||||
|
public static ClassLoader newClassLoader() {
|
||||||
|
try {
|
||||||
|
return new URLClassLoader(new URL[] {
|
||||||
|
Paths.get(System.getProperty("test.classes",".")).toUri().toURL(),
|
||||||
|
}, null);
|
||||||
|
} catch (MalformedURLException e){
|
||||||
|
throw new RuntimeException("Unexpected URL conversion failure", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static public Class Test_class;
|
||||||
|
|
||||||
|
static public void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
// loader2 must be first on the list so loader 1 must be used first
|
||||||
|
ClassLoader loader1 = newClassLoader();
|
||||||
|
Class dummy = loader1.loadClass("Test");
|
||||||
|
|
||||||
|
ClassLoader loader2 = newClassLoader();
|
||||||
|
|
||||||
|
Test_class = loader2.loadClass("Test");
|
||||||
|
Method m3 = Test_class.getMethod("m3", ClassLoader.class);
|
||||||
|
// Add speculative trap in m2() (loaded by loader1) that
|
||||||
|
// references m4() (loaded by loader2).
|
||||||
|
m3.invoke(Test_class.newInstance(), loader1);
|
||||||
|
|
||||||
|
String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();
|
||||||
|
int p = nameOfRunningVM.indexOf('@');
|
||||||
|
String pid = nameOfRunningVM.substring(0, p);
|
||||||
|
|
||||||
|
// Make the nmethod go away
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redefine class Test loaded by loader2
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
try {
|
||||||
|
VirtualMachine vm = VirtualMachine.attach(pid);
|
||||||
|
vm.loadAgent(System.getProperty("test.classes",".") + "/agent.jar", "");
|
||||||
|
vm.detach();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Will process loader2 first, find m4() is redefined and
|
||||||
|
// needs to be freed then process loader1, check the
|
||||||
|
// speculative trap in m2() and try to access m4() which was
|
||||||
|
// freed already.
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized byte[] transform(final ClassLoader classLoader,
|
||||||
|
final String className,
|
||||||
|
Class<?> classBeingRedefined,
|
||||||
|
ProtectionDomain protectionDomain,
|
||||||
|
byte[] classfileBuffer) {
|
||||||
|
System.out.println("Transforming class " + className + " "+ classLoader);
|
||||||
|
return classfileBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
instrumentation.retransformClasses(to_redefine);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void agentmain(String agentArgs, Instrumentation instrumentation) throws Exception {
|
||||||
|
Agent transformer = new Agent();
|
||||||
|
instrumentation.addTransformer(transformer, true);
|
||||||
|
|
||||||
|
redefine(agentArgs, instrumentation, Test_class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
public class B extends A {
|
||||||
|
void m() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/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.
|
||||||
|
*/
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import com.oracle.java.testlibrary.*;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8040237
|
||||||
|
* @library /testlibrary
|
||||||
|
* @build Agent Test A B
|
||||||
|
* @run main ClassFileInstaller Agent
|
||||||
|
* @run main Launcher
|
||||||
|
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -XX:ReservedCodeCacheSize=3M Agent
|
||||||
|
*/
|
||||||
|
public class Launcher {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
PrintWriter pw = new PrintWriter("MANIFEST.MF");
|
||||||
|
pw.println("Agent-Class: Agent");
|
||||||
|
pw.println("Can-Retransform-Classes: true");
|
||||||
|
pw.close();
|
||||||
|
|
||||||
|
ProcessBuilder pb = new ProcessBuilder();
|
||||||
|
pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", System.getProperty("test.classes",".") + "/agent.jar", "Agent.class"});
|
||||||
|
pb.start().waitFor();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
|
||||||
|
public boolean m1(A a, Boolean early_return) {
|
||||||
|
if (early_return.booleanValue()) return true;
|
||||||
|
boolean res = m2(a);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean m2(A a) {
|
||||||
|
boolean res = false;
|
||||||
|
if (a.getClass() == B.class) {
|
||||||
|
a.m();
|
||||||
|
} else {
|
||||||
|
res = true;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void m3(ClassLoader loader) throws Exception {
|
||||||
|
Class Test_class = loader.loadClass("Test");
|
||||||
|
Object test = Test_class.newInstance();
|
||||||
|
Class A_class = loader.loadClass("A");
|
||||||
|
Object a = A_class.newInstance();
|
||||||
|
Class B_class = loader.loadClass("B");
|
||||||
|
Object b = B_class.newInstance();
|
||||||
|
Method m1 = Test_class.getMethod("m1", A_class, Boolean.class);
|
||||||
|
|
||||||
|
// So we don't hit uncommon trap in the next loop
|
||||||
|
for (int i = 0; i < 4000; i++) {
|
||||||
|
m4(m1, test, a, Boolean.TRUE);
|
||||||
|
m4(m1, test, b, Boolean.TRUE);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 20000; i++) {
|
||||||
|
m4(m1, test, a, Boolean.FALSE);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
m4(m1, test, b, Boolean.FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object m4(Method m, Object test, Object a, Object early_return) throws Exception {
|
||||||
|
return m.invoke(test, a, early_return);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public A a = new A();
|
||||||
|
static public B b = new B();
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue