Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8268470: CDS dynamic dump asserts with JFR RecordingStream #4467

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 19 additions & 1 deletion src/hotspot/share/classfile/systemDictionaryShared.cpp
Expand Up @@ -1354,11 +1354,29 @@ bool SystemDictionaryShared::check_for_exclusion(InstanceKlass* k, DumpTimeShare
return info->is_excluded();
}

// Check if a class or any of its supertypes has been redefined.
bool SystemDictionaryShared::has_been_redefined(InstanceKlass* k) {
if (k->has_been_redefined()) {
return true;
}
if (k->java_super() != NULL && has_been_redefined(k->java_super())) {
return true;
}
Array<InstanceKlass*>* interfaces = k->local_interfaces();
int len = interfaces->length();
for (int i = 0; i < len; i++) {
if (has_been_redefined(interfaces->at(i))) {
return true;
}
}
return false;
}

bool SystemDictionaryShared::check_for_exclusion_impl(InstanceKlass* k) {
if (k->is_in_error_state()) {
return warn_excluded(k, "In error state");
}
if (k->has_been_redefined()) {
if (has_been_redefined(k)) {
return warn_excluded(k, "Has been redefined");
}
if (!k->is_hidden() && k->shared_classpath_index() < 0 && is_builtin(k)) {
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/classfile/systemDictionaryShared.hpp
Expand Up @@ -215,6 +215,7 @@ class SystemDictionaryShared: public SystemDictionary {
static bool is_registered_lambda_proxy_class(InstanceKlass* ik);
static bool warn_excluded(InstanceKlass* k, const char* reason);
static bool check_for_exclusion_impl(InstanceKlass* k);
static bool has_been_redefined(InstanceKlass* k);

static bool _dump_in_progress;
DEBUG_ONLY(static bool _no_class_loading_should_happen;)
Expand Down
@@ -0,0 +1,78 @@
/*
* Copyright (c) 2021, 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.
*
*/

/*
* @test
* @bug 8268470
* @summary Test dynamic CDS with JFR recording.
* Dynamic dump should skip the class such as jdk/jfr/events/FileReadEvent
* if one of its super classes has been redefined during JFR startup.
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @build JFRDynamicCDSApp sun.hotspot.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar jfr_dynamic_cds_app.jar JFRDynamicCDSApp JFRDynamicCDSApp$StressEvent
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. JFRDynamicCDS
*/

import jdk.test.lib.helpers.ClassFileInstaller;

public class JFRDynamicCDS extends DynamicArchiveTestBase {
public static void main(String[] args) throws Exception {
runTest(JFRDynamicCDS::test);
}

static void test() throws Exception {
String topArchiveName = getNewArchiveName();
String appJar = ClassFileInstaller.getJarPath("jfr_dynamic_cds_app.jar");
String mainClass = "JFRDynamicCDSApp";
// 0 : without JFR recording
// 4 : with JFR recording
int[] modes = {0, 4};

for (int mode : modes) {
dump(topArchiveName,
"-Xlog:class+load,cds=debug",
"-cp", appJar, mainClass, String.valueOf(mode))
.assertNormalExit(output -> {
output.shouldHaveExitValue(0);
if (mode == 4) {
output.shouldMatch("Skipping.jdk/jfr/events.*Has.been.redefined");
}
});

run(topArchiveName,
"-Xlog:class+load=info",
"-cp", appJar, mainClass, String.valueOf(mode))
.assertNormalExit(output -> {
output.shouldHaveExitValue(0)
.shouldContain("[class,load] JFRDynamicCDSApp source: shared objects file (top)");
if (mode == 4) {
output.shouldMatch(".class.load. jdk.jfr.events.*source:.*jrt:/jdk.jfr");
}
});
}
}
}
@@ -0,0 +1,95 @@
/*
* Copyright (c) 2021, 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.nio.file.Paths;
import jdk.jfr.Configuration;
import jdk.jfr.Description;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.Recording;
import jdk.jfr.consumer.RecordingStream;

public class JFRDynamicCDSApp {
public static void main(String args[]) throws Exception {
int mode = 4;
try {
mode = Integer.parseInt(args[0]);
} catch (Throwable t) {}

if (mode > 0) {
RecordingStream rs = new RecordingStream();
if (mode > 1) {
rs.enable("JFRDynamicCDS.StressEvent");
rs.startAsync();

if (mode > 2) {
Recording recording = startRecording();
if (mode > 3) {
loop();
}
recording.stop();
recording.close();
}
}

rs.close();
}
}

static Recording startRecording() throws Exception {
Configuration configuration = Configuration.getConfiguration("default");
Recording recording = new Recording(configuration);

recording.setName("internal");
recording.enable(StressEvent.class);
recording.setDestination(Paths.get("JFRDynamicCDS.jfr"));
recording.start();
return recording;
}


static void loop() {
for (int i=0; i<100; i++) {
StressEvent event = new StressEvent();
event.iteration = i;
event.description = "Stressful Event, take it easy!";
event.customClazz = StressEvent.class;
event.value = i;
event.commit();
}
}


/**
* Internal StressEvent class.
*/
@Label("Stress Event")
@Description("A duration event with 4 entries")
@Name("JFRDynamicCDS.StressEvent")
public static class StressEvent extends jdk.jfr.Event {
public Class<?> customClazz;
public String description;
public int iteration;
public double value;
}
}