diff --git a/src/hotspot/share/jfr/support/jfrIntrinsics.hpp b/src/hotspot/share/jfr/support/jfrIntrinsics.hpp index 77affc69926..31a81e7d7b5 100644 --- a/src/hotspot/share/jfr/support/jfrIntrinsics.hpp +++ b/src/hotspot/share/jfr/support/jfrIntrinsics.hpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2012, 2025, 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 @@ -49,7 +49,7 @@ class JfrIntrinsicSupport : AllStatic { #define JFR_TEMPLATES(template) \ template(jdk_jfr_internal_management_HiddenWait, "jdk/jfr/internal/management/HiddenWait") \ template(jdk_jfr_internal_JVM, "jdk/jfr/internal/JVM") \ - template(jdk_jfr_internal_event_EventWriterFactory, "jdk/jfr/internal/event/EventWriterFactory") \ + template(jdk_jfr_internal_event_EventWriter, "jdk/jfr/internal/event/EventWriter") \ template(jdk_jfr_internal_event_EventConfiguration_signature, "Ljdk/jfr/internal/event/EventConfiguration;") \ template(getEventWriter_signature, "()Ljdk/jfr/internal/event/EventWriter;") \ template(eventConfiguration_name, "eventConfiguration") \ diff --git a/src/hotspot/share/jfr/support/jfrResolution.cpp b/src/hotspot/share/jfr/support/jfrResolution.cpp index 486067c485a..0a4c8a1f3f1 100644 --- a/src/hotspot/share/jfr/support/jfrResolution.cpp +++ b/src/hotspot/share/jfr/support/jfrResolution.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -182,7 +182,7 @@ static inline const Method* ljf_sender_method(JavaThread* jt) { return ljf.method(); } -static const char* const link_error_msg = "illegal access linking method 'jdk.jfr.internal.event.EventWriterFactory.getEventWriter(long)'"; +static const char* const link_error_msg = "illegal access linking method 'jdk.jfr.internal.event.EventWriter.getEventWriter()'"; void JfrResolution::on_runtime_resolution(const CallInfo & info, TRAPS) { assert(info.selected_method() != nullptr, "invariant"); @@ -199,12 +199,12 @@ void JfrResolution::on_runtime_resolution(const CallInfo & info, TRAPS) { if (method->name() != event_writer_method_name) { return; } - static const Symbol* const event_writer_factory_klass_name = vmSymbols::jdk_jfr_internal_event_EventWriterFactory(); - assert(event_writer_factory_klass_name != nullptr, "invariant"); - if (info.resolved_klass()->name() != event_writer_factory_klass_name) { + static const Symbol* const event_writer_klass_name = vmSymbols::jdk_jfr_internal_event_EventWriter(); + assert(event_writer_klass_name != nullptr, "invariant"); + if (info.resolved_klass()->name() != event_writer_klass_name) { return; } - // Attempting to link against jdk.jfr.internal.event.EventWriterFactory.getEventWriter(). + // Attempting to link against jdk.jfr.internal.event.EventWriter.getEventWriter(). // The sender, i.e. the method attempting to link, is in the ljf (if one exists). const Method* const sender = ljf_sender_method(THREAD); if (sender == nullptr) { @@ -228,9 +228,9 @@ void JfrResolution::on_runtime_resolution(const CallInfo & info, TRAPS) { } static inline bool is_compiler_linking_event_writer(const Symbol* holder, const Symbol* name) { - static const Symbol* const event_writer_factory_klass_name = vmSymbols::jdk_jfr_internal_event_EventWriterFactory(); - assert(event_writer_factory_klass_name != nullptr, "invariant"); - if (holder != event_writer_factory_klass_name) { + static const Symbol* const event_writer_klass_name = vmSymbols::jdk_jfr_internal_event_EventWriter(); + assert(event_writer_klass_name != nullptr, "invariant"); + if (holder != event_writer_klass_name) { return false; } static const Symbol* const event_writer_method_name = vmSymbols::getEventWriter_name(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/AnnotationElement.java b/src/jdk.jfr/share/classes/jdk/jfr/AnnotationElement.java index 108498c340d..046709fa92e 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/AnnotationElement.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/AnnotationElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -37,7 +37,6 @@ import java.util.Objects; import java.util.Set; import java.util.StringJoiner; -import jdk.jfr.internal.SecuritySupport; import jdk.jfr.internal.Type; import jdk.jfr.internal.TypeLibrary; import jdk.jfr.internal.util.Utils; @@ -115,7 +114,6 @@ public final class AnnotationElement { public AnnotationElement(Class annotationType, Map values) { Objects.requireNonNull(annotationType, "annotationType"); Objects.requireNonNull(values, "values"); - SecuritySupport.checkRegisterPermission(); // copy values to avoid modification after validation HashMap map = new HashMap<>(values); for (Map.Entry entry : map.entrySet()) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/EventFactory.java b/src/jdk.jfr/share/classes/jdk/jfr/EventFactory.java index fc7b61e8756..282e1ae598f 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/EventFactory.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/EventFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -37,7 +37,6 @@ import jdk.internal.module.Checks; import jdk.jfr.internal.EventClassBuilder; import jdk.jfr.internal.JVMSupport; import jdk.jfr.internal.MetadataRepository; -import jdk.jfr.internal.SecuritySupport; import jdk.jfr.internal.Type; import jdk.jfr.internal.util.Utils; @@ -99,8 +98,6 @@ public final class EventFactory { Objects.requireNonNull(fields, "fields"); JVMSupport.ensureWithInternalError(); - SecuritySupport.checkRegisterPermission(); - List sanitizedAnnotation = Utils.sanitizeNullFreeList(annotationElements, AnnotationElement.class); List sanitizedFields = Utils.sanitizeNullFreeList(fields, ValueDescriptor.class); Set nameSet = HashSet.newHashSet(sanitizedFields.size()); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java index 774b36b97d7..a7bf3976d14 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -29,8 +29,6 @@ import static jdk.jfr.internal.LogLevel.DEBUG; import static jdk.jfr.internal.LogLevel.INFO; import static jdk.jfr.internal.LogTag.JFR; -import java.security.AccessControlContext; -import java.security.AccessController; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -44,7 +42,6 @@ import jdk.jfr.internal.Options; import jdk.jfr.internal.PlatformRecorder; import jdk.jfr.internal.PlatformRecording; import jdk.jfr.internal.Repository; -import jdk.jfr.internal.SecuritySupport; import jdk.jfr.internal.util.Utils; import jdk.jfr.internal.periodic.PeriodicEvents; @@ -157,7 +154,6 @@ public final class FlightRecorder { */ public static FlightRecorder getFlightRecorder() throws IllegalStateException { synchronized (PlatformRecorder.class) { - SecuritySupport.checkAccessFlightRecorder(); JVMSupport.ensureWithIllegalStateException(); if (platformRecorder == null) { try { @@ -213,10 +209,7 @@ public final class FlightRecorder { } Utils.ensureValidEventSubclass(eventClass); - SecuritySupport.checkRegisterPermission(); - @SuppressWarnings("removal") - AccessControlContext acc = AccessController.getContext(); - PeriodicEvents.addUserEvent(acc, eventClass, hook); + PeriodicEvents.addJavaEvent(eventClass, hook); } /** @@ -227,7 +220,6 @@ public final class FlightRecorder { */ public static boolean removePeriodicEvent(Runnable hook) { Objects.requireNonNull(hook, "hook"); - SecuritySupport.checkRegisterPermission(); if (JVMSupport.isNotAvailable()) { return false; } @@ -260,7 +252,6 @@ public final class FlightRecorder { */ public static void addListener(FlightRecorderListener changeListener) { Objects.requireNonNull(changeListener, "changeListener"); - SecuritySupport.checkAccessFlightRecorder(); if (JVMSupport.isNotAvailable()) { return; } @@ -280,7 +271,6 @@ public final class FlightRecorder { */ public static boolean removeListener(FlightRecorderListener changeListener) { Objects.requireNonNull(changeListener, "changeListener"); - SecuritySupport.checkAccessFlightRecorder(); if (JVMSupport.isNotAvailable()) { return false; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java index 5a2dc51bc41..67e844ac269 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -25,7 +25,6 @@ package jdk.jfr; -import java.security.AccessControlContext; import java.util.List; import java.util.Map; import java.util.Objects; @@ -34,7 +33,6 @@ import jdk.jfr.internal.PlatformEventType; import jdk.jfr.internal.PlatformRecorder; import jdk.jfr.internal.PlatformRecording; import jdk.jfr.internal.PrivateAccess; -import jdk.jfr.internal.SecuritySupport; import jdk.jfr.internal.Type; import jdk.jfr.internal.management.EventSettingsModifier; @@ -156,12 +154,6 @@ public final class FlightRecorderPermission extends java.security.BasicPermissio return FlightRecorder.getFlightRecorder().getInternal(); } - @SuppressWarnings("removal") - @Override - public AccessControlContext getContext(SettingControl settingControl) { - return settingControl.getContext(); - } - @Override public EventSettings newEventSettings(EventSettingsModifier esm) { return new EventSettings.DelegatedEventSettings(esm); @@ -184,7 +176,7 @@ public final class FlightRecorderPermission extends java.security.BasicPermissio */ public FlightRecorderPermission(String name) { super(Objects.requireNonNull(name, "name")); - if (!name.equals(SecuritySupport.ACCESS_FLIGHT_RECORDER) && !name.equals(SecuritySupport.REGISTER_EVENT)) { + if (!name.equals("accessFlightRecorder") && !name.equals("registerEvent")) { throw new IllegalArgumentException("name: " + name); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/Recording.java b/src/jdk.jfr/share/classes/jdk/jfr/Recording.java index 6168ddb2832..333645f1731 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/Recording.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Recording.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -39,7 +39,7 @@ import jdk.jfr.internal.PlatformRecorder; import jdk.jfr.internal.PlatformRecording; import jdk.jfr.internal.Type; import jdk.jfr.internal.util.Utils; -import jdk.jfr.internal.WriteableUserPath; +import jdk.jfr.internal.WriteablePath; /** * Provides means to configure, start, stop and dump recording data to disk. @@ -368,7 +368,7 @@ public final class Recording implements Closeable { */ public void dump(Path destination) throws IOException { Objects.requireNonNull(destination, "destination"); - internal.dump(new WriteableUserPath(destination)); + internal.dump(new WriteablePath(destination)); } /** @@ -461,7 +461,7 @@ public final class Recording implements Closeable { * @throws IOException if the path is not writable */ public void setDestination(Path destination) throws IOException { - internal.setDestination(destination != null ? new WriteableUserPath(destination) : null); + internal.setDestination(destination != null ? new WriteablePath(destination) : null); } /** @@ -471,11 +471,11 @@ public final class Recording implements Closeable { * @return the destination file, or {@code null} if not set. */ public Path getDestination() { - WriteableUserPath usp = internal.getDestination(); - if (usp == null) { + WriteablePath wp = internal.getDestination(); + if (wp == null) { return null; } else { - return usp.getPotentiallyMaliciousOriginal(); + return wp.getPath(); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/SettingControl.java b/src/jdk.jfr/share/classes/jdk/jfr/SettingControl.java index 1c699247800..ac73f6d4c12 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/SettingControl.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/SettingControl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -25,12 +25,8 @@ package jdk.jfr; -import java.security.AccessControlContext; -import java.security.AccessController; import java.util.Set; -import jdk.jfr.internal.settings.JDKSettingControl; - /** * Base class to extend to create setting controls. *

@@ -77,30 +73,10 @@ import jdk.jfr.internal.settings.JDKSettingControl; @MetadataDefinition public abstract class SettingControl { - @SuppressWarnings("removal") - private final AccessControlContext context; - private final boolean initialized; - /** * Constructor for invocation by subclass constructors. */ - @SuppressWarnings("removal") protected SettingControl() { - context = this instanceof JDKSettingControl ? null : AccessController.getContext(); - initialized = true; - } - - @SuppressWarnings("removal") - final AccessControlContext getContext() { - // Ensure object state is safe - if (!initialized) { - throw new InternalError("Object must be initialized before security context can be retrieved"); - } - AccessControlContext c = this.context; - if (c == null && !(this instanceof JDKSettingControl)) { - throw new InternalError("Security context can only be null for trusted setting controls"); - } - return c; } /** diff --git a/src/jdk.jfr/share/classes/jdk/jfr/ValueDescriptor.java b/src/jdk.jfr/share/classes/jdk/jfr/ValueDescriptor.java index ff485aa96e7..9994b689d09 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/ValueDescriptor.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/ValueDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -31,7 +31,6 @@ import java.util.List; import java.util.Objects; import jdk.jfr.internal.AnnotationConstruct; -import jdk.jfr.internal.SecuritySupport; import jdk.jfr.internal.Type; import jdk.jfr.internal.util.Utils; @@ -143,7 +142,6 @@ public final class ValueDescriptor { Objects.requireNonNull(type, "type"); Objects.requireNonNull(name, "name"); Objects.requireNonNull(annotations, "annotations"); - SecuritySupport.checkRegisterPermission(); if (!allowArray) { if (type.isArray()) { throw new IllegalArgumentException("Array types are not allowed"); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java index 1a1c468add9..ac325f19f22 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -27,18 +27,14 @@ package jdk.jfr.consumer; import java.io.IOException; import java.nio.file.Path; -import java.security.AccessControlContext; -import java.security.AccessController; import java.time.Duration; import java.time.Instant; import java.util.Collections; import java.util.Objects; import java.util.function.Consumer; -import jdk.jfr.internal.SecuritySupport; import jdk.jfr.internal.consumer.EventDirectoryStream; import jdk.jfr.internal.consumer.EventFileStream; -import jdk.jfr.internal.consumer.FileAccess; /** * Represents a stream of events. @@ -113,13 +109,9 @@ public interface EventStream extends AutoCloseable { * @throws IOException if a stream can't be opened, or an I/O error occurs * when trying to access the repository */ - @SuppressWarnings("removal") public static EventStream openRepository() throws IOException { - SecuritySupport.checkAccessFlightRecorder(); return new EventDirectoryStream( - AccessController.getContext(), null, - SecuritySupport.PRIVILEGED, null, Collections.emptyList(), false @@ -143,12 +135,8 @@ public interface EventStream extends AutoCloseable { */ public static EventStream openRepository(Path directory) throws IOException { Objects.requireNonNull(directory, "directory"); - @SuppressWarnings("removal") - AccessControlContext acc = AccessController.getContext(); return new EventDirectoryStream( - acc, directory, - FileAccess.UNPRIVILEGED, null, Collections.emptyList(), true @@ -169,10 +157,9 @@ public interface EventStream extends AutoCloseable { * @throws IOException if the file can't be opened, or an I/O error occurs * during reading */ - @SuppressWarnings("removal") static EventStream openFile(Path file) throws IOException { Objects.requireNonNull(file, "file"); - return new EventFileStream(AccessController.getContext(), file); + return new EventFileStream(file); } /** diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java index 0437ec59589..0e51da04119 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -43,7 +43,6 @@ import jdk.jfr.internal.consumer.ChunkParser.ParserConfiguration; import jdk.jfr.internal.consumer.ParserFilter; import jdk.jfr.internal.consumer.ChunkHeader; import jdk.jfr.internal.consumer.ChunkParser; -import jdk.jfr.internal.consumer.FileAccess; import jdk.jfr.internal.consumer.ParserState; import jdk.jfr.internal.consumer.RecordingInput; import jdk.jfr.internal.consumer.filter.ChunkWriter; @@ -81,7 +80,7 @@ public final class RecordingFile implements Closeable { public RecordingFile(Path file) throws IOException { Objects.requireNonNull(file, "file"); this.file = file.toFile(); - this.input = new RecordingInput(this.file, FileAccess.UNPRIVILEGED); + this.input = new RecordingInput(this.file); this.chunkWriter = null; findNext(); } @@ -146,7 +145,7 @@ public final class RecordingFile implements Closeable { MetadataDescriptor previous = null; List types = new ArrayList<>(); HashSet foundIds = new HashSet<>(); - try (RecordingInput ri = new RecordingInput(file, FileAccess.UNPRIVILEGED)) { + try (RecordingInput ri = new RecordingInput(file)) { ChunkHeader ch = new ChunkHeader(ri); aggregateEventTypeForChunk(ch, null, types, foundIds); while (!ch.isLastChunk()) { @@ -162,7 +161,7 @@ public final class RecordingFile implements Closeable { MetadataDescriptor previous = null; List types = new ArrayList<>(200); HashSet foundIds = HashSet.newHashSet(types.size()); - try (RecordingInput ri = new RecordingInput(file, FileAccess.UNPRIVILEGED)) { + try (RecordingInput ri = new RecordingInput(file)) { ChunkHeader ch = new ChunkHeader(ri); ch.awaitFinished(); aggregateTypeForChunk(ch, null, types, foundIds); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java index 2e7d23bb84c..3d6c8de3015 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -27,8 +27,6 @@ package jdk.jfr.consumer; import java.io.IOException; import java.nio.file.Path; -import java.security.AccessControlContext; -import java.security.AccessController; import java.time.Duration; import java.time.Instant; import java.util.Collections; @@ -45,7 +43,6 @@ import jdk.jfr.Recording; import jdk.jfr.RecordingState; import jdk.jfr.internal.PlatformRecording; import jdk.jfr.internal.PrivateAccess; -import jdk.jfr.internal.SecuritySupport; import jdk.jfr.internal.util.Utils; import jdk.jfr.internal.consumer.EventDirectoryStream; import jdk.jfr.internal.management.StreamBarrier; @@ -98,18 +95,13 @@ public final class RecordingStream implements AutoCloseable, EventStream { } private RecordingStream(Map settings) { - SecuritySupport.checkAccessFlightRecorder(); - @SuppressWarnings("removal") - AccessControlContext acc = AccessController.getContext(); this.recording = new Recording(); this.creationTime = Instant.now(); this.recording.setName("Recording Stream: " + creationTime); try { PlatformRecording pr = PrivateAccess.getInstance().getPlatformRecording(recording); this.directoryStream = new EventDirectoryStream( - acc, null, - SecuritySupport.PRIVILEGED, pr, configurations(), false diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java index 7cc399019e6..4c8913e96a0 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, 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 @@ -28,6 +28,7 @@ package jdk.jfr.internal; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -65,7 +66,7 @@ final class ChunkInputStream extends InputStream { return false; } - stream = new BufferedInputStream(SecuritySupport.newFileInputStream(currentChunk.getFile())); + stream = new BufferedInputStream(Files.newInputStream(currentChunk.getFile())); unstreamedSize -= currentChunk.getSize(); return true; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/Control.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/Control.java index 8f246948710..b21b539cab8 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Control.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Control.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -25,23 +25,16 @@ package jdk.jfr.internal; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Collections; import java.util.HashSet; import java.util.Objects; import java.util.Set; import jdk.jfr.SettingControl; -import jdk.jfr.internal.settings.JDKSettingControl; import jdk.jfr.internal.settings.PeriodSetting; import jdk.jfr.internal.settings.StackTraceSetting; import jdk.jfr.internal.settings.ThresholdSetting; final class Control { - @SuppressWarnings("removal") - private final AccessControlContext context; private static final int CACHE_SIZE = 5; private final Set[] cachedUnions = new HashSet[CACHE_SIZE]; private final String[] cachedValues = new String[CACHE_SIZE]; @@ -51,12 +44,8 @@ final class Control { // called by exposed subclass in external API public Control(SettingControl delegate, String defaultValue) { - this.context = PrivateAccess.getInstance().getContext(delegate); this.delegate = delegate; this.defaultValue = defaultValue; - if (this.context == null && !(delegate instanceof JDKSettingControl)) { - throw new InternalError("Security context can only be null for trusted setting controls"); - } } boolean isType(Class clazz) { @@ -74,25 +63,8 @@ final class Control { apply(defaultValue); } - @SuppressWarnings("removal") public String getValue() { - if (context == null) { - // VM events requires no access control context - return delegate.getValue(); - } else { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public String run() { - try { - return delegate.getValue(); - } catch (Throwable t) { - // Prevent malicious user to propagate exception callback in the wrong context - Logger.log(LogTag.JFR_SETTING, LogLevel.WARN, "Exception occurred when trying to get value for " + getClass()); - } - return defaultValue != null ? defaultValue : ""; // Need to return something - } - }, context); - } + return delegate.getValue(); } private void apply(String value) { @@ -102,53 +74,18 @@ final class Control { setValue(value); } - @SuppressWarnings("removal") public void setValue(String value) { - if (context == null) { - // VM events requires no access control context - try { - delegate.setValue(value); - lastValue = delegate.getValue(); - } catch (Throwable t) { - Logger.log(LogTag.JFR_SETTING, LogLevel.WARN, "Exception occurred when setting value \"" + value + "\" for " + getClass()); - lastValue = null; - } - } else { - lastValue = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public String run() { - try { - delegate.setValue(value); - return delegate.getValue(); - } catch (Throwable t) { - // Prevent malicious user to propagate exception callback in the wrong context - Logger.log(LogTag.JFR_SETTING, LogLevel.WARN, "Exception occurred when setting value \"" + value + "\" for " + getClass()); - } - return null; - } - }, context); + try { + delegate.setValue(value); + lastValue = delegate.getValue(); + } catch (Throwable t) { + Logger.log(LogTag.JFR_SETTING, LogLevel.WARN, "Exception occurred when setting value \"" + value + "\". " + t.getMessage()); + lastValue = null; } } - - @SuppressWarnings("removal") public String combine(Set values) { - if (context == null) { - // VM events requires no access control context - return delegate.combine(values); - } - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public String run() { - try { - return delegate.combine(Collections.unmodifiableSet(values)); - } catch (Throwable t) { - // Prevent malicious user to propagate exception callback in the wrong context - Logger.log(LogTag.JFR_SETTING, LogLevel.WARN, "Exception occurred when combining " + values + " for " + getClass()); - } - return null; - } - }, context); + return delegate.combine(values); } private final String findCombine(Set values) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java index f086bbf8847..19e2febf88e 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -280,7 +280,7 @@ public final class EventControl { } catch (Exception e) { throw (Error) new InternalError("Could not get constructor for " + settingControlClass.getName()).initCause(e); } - SecuritySupport.setAccessible(cc); + cc.setAccessible(true); try { return (SettingControl) cc.newInstance(); } catch (IllegalArgumentException | InvocationTargetException e) { @@ -373,13 +373,6 @@ public final class EventControl { return idName; } - /** - * A malicious user must never be able to run a callback in the wrong - * context. Methods on SettingControl must therefore never be invoked directly - * by JFR, instead use jdk.jfr.internal.Control. - * - * The returned list is only to be used inside EventConfiguration - */ public List getSettingControls() { return settingControls; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java index d962a535829..636ae3756e6 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -89,7 +89,6 @@ final class EventInstrumentation { private static final ClassDesc TYPE_EVENT_CONFIGURATION = classDesc(EventConfiguration.class); private static final ClassDesc TYPE_ISE = Bytecode.classDesc(IllegalStateException.class); private static final ClassDesc TYPE_EVENT_WRITER = classDesc(EventWriter.class); - private static final ClassDesc TYPE_EVENT_WRITER_FACTORY = ClassDesc.of("jdk.jfr.internal.event.EventWriterFactory"); private static final ClassDesc TYPE_OBJECT = Bytecode.classDesc(Object.class); private static final ClassDesc TYPE_SETTING_DEFINITION = Bytecode.classDesc(SettingDefinition.class); private static final MethodDesc METHOD_BEGIN = MethodDesc.of("begin", "()V"); @@ -100,7 +99,7 @@ final class EventInstrumentation { private static final MethodDesc METHOD_EVENT_CONFIGURATION_SHOULD_COMMIT = MethodDesc.of("shouldCommit", "(J)Z"); private static final MethodDesc METHOD_EVENT_CONFIGURATION_GET_SETTING = MethodDesc.of("getSetting", SettingControl.class, int.class); private static final MethodDesc METHOD_EVENT_SHOULD_COMMIT = MethodDesc.of("shouldCommit", "()Z"); - private static final MethodDesc METHOD_GET_EVENT_WRITER_KEY = MethodDesc.of("getEventWriter", "(J)" + TYPE_EVENT_WRITER.descriptorString()); + private static final MethodDesc METHOD_GET_EVENT_WRITER = MethodDesc.of("getEventWriter", "()" + TYPE_EVENT_WRITER.descriptorString()); private static final MethodDesc METHOD_IS_ENABLED = MethodDesc.of("isEnabled", "()Z"); private static final MethodDesc METHOD_RESET = MethodDesc.of("reset", "()V"); private static final MethodDesc METHOD_SHOULD_COMMIT_LONG = MethodDesc.of("shouldCommit", "(J)Z"); @@ -767,8 +766,7 @@ final class EventInstrumentation { } private void getEventWriter(CodeBuilder codeBuilder) { - codeBuilder.ldc(EventWriterKey.getKey()); - invokestatic(codeBuilder, TYPE_EVENT_WRITER_FACTORY, METHOD_GET_EVENT_WRITER_KEY); + invokestatic(codeBuilder, TYPE_EVENT_WRITER, METHOD_GET_EVENT_WRITER); } private void getEventConfiguration(CodeBuilder codeBuilder) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/FilePurger.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/FilePurger.java index e643741adf5..f6649796a4d 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/FilePurger.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/FilePurger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -26,19 +26,19 @@ package jdk.jfr.internal; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.SequencedSet; -import jdk.jfr.internal.SecuritySupport.SafePath; - // This class keeps track of files that can't be deleted // so they can at a later staged be removed. final class FilePurger { - private static final SequencedSet paths = new LinkedHashSet<>(); + private static final SequencedSet paths = new LinkedHashSet<>(); - public static synchronized void add(SafePath p) { + public static synchronized void add(Path p) { paths.add(p); if (paths.size() > 1000) { removeOldest(); @@ -50,7 +50,7 @@ final class FilePurger { return; } - for (SafePath p : new ArrayList<>(paths)) { + for (Path p : new ArrayList<>(paths)) { if (delete(p)) { paths.remove(p); } @@ -61,16 +61,12 @@ final class FilePurger { paths.removeFirst(); } - private static boolean delete(SafePath p) { - try { - if (!SecuritySupport.exists(p)) { - return true; - } - } catch (IOException e) { - // ignore + private static boolean delete(Path p) { + if (!Files.exists(p)) { + return true; } try { - SecuritySupport.delete(p); + Files.delete(p); return true; } catch (IOException e) { return false; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java index d0d186e2479..f0b7dcc2bf2 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -91,11 +91,11 @@ public final class JDKEvents { try { if (initializationTriggered == false) { for (Class eventClass : eventClasses) { - SecuritySupport.registerEvent((Class) eventClass); + MetadataRepository.getInstance().register((Class) eventClass); } - PeriodicEvents.addJDKEvent(jdk.internal.event.ExceptionStatisticsEvent.class, emitExceptionStatistics); - PeriodicEvents.addJDKEvent(DirectBufferStatisticsEvent.class, emitDirectBufferStatistics); - PeriodicEvents.addJDKEvent(InitialSecurityPropertyEvent.class, emitInitialSecurityProperties); + PeriodicEvents.addJavaEvent(jdk.internal.event.ExceptionStatisticsEvent.class, emitExceptionStatistics); + PeriodicEvents.addJavaEvent(DirectBufferStatisticsEvent.class, emitDirectBufferStatistics); + PeriodicEvents.addJavaEvent(InitialSecurityPropertyEvent.class, emitInitialSecurityProperties); initializeContainerEvents(); JFRTracing.enable(); @@ -116,17 +116,21 @@ public final class JDKEvents { } // The registration of events and hooks are needed to provide metadata, // even when not running in a container - SecuritySupport.registerEvent(ContainerConfigurationEvent.class); - SecuritySupport.registerEvent(ContainerCPUUsageEvent.class); - SecuritySupport.registerEvent(ContainerCPUThrottlingEvent.class); - SecuritySupport.registerEvent(ContainerMemoryUsageEvent.class); - SecuritySupport.registerEvent(ContainerIOUsageEvent.class); + registerEvent(ContainerConfigurationEvent.class); + registerEvent(ContainerCPUUsageEvent.class); + registerEvent(ContainerCPUThrottlingEvent.class); + registerEvent(ContainerMemoryUsageEvent.class); + registerEvent(ContainerIOUsageEvent.class); - PeriodicEvents.addJDKEvent(ContainerConfigurationEvent.class, emitContainerConfiguration); - PeriodicEvents.addJDKEvent(ContainerCPUUsageEvent.class, emitContainerCPUUsage); - PeriodicEvents.addJDKEvent(ContainerCPUThrottlingEvent.class, emitContainerCPUThrottling); - PeriodicEvents.addJDKEvent(ContainerMemoryUsageEvent.class, emitContainerMemoryUsage); - PeriodicEvents.addJDKEvent(ContainerIOUsageEvent.class, emitContainerIOUsage); + PeriodicEvents.addJavaEvent(ContainerConfigurationEvent.class, emitContainerConfiguration); + PeriodicEvents.addJavaEvent(ContainerCPUUsageEvent.class, emitContainerCPUUsage); + PeriodicEvents.addJavaEvent(ContainerCPUThrottlingEvent.class, emitContainerCPUThrottling); + PeriodicEvents.addJavaEvent(ContainerMemoryUsageEvent.class, emitContainerMemoryUsage); + PeriodicEvents.addJavaEvent(ContainerIOUsageEvent.class, emitContainerIOUsage); + } + + private static void registerEvent(Class eventClass) { + MetadataRepository.getInstance().register(eventClass); } private static void emitExceptionStatistics() { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMSupport.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMSupport.java index 7fde28a3d21..ded1f78b76e 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMSupport.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -56,7 +56,7 @@ public final class JVMSupport { private static boolean checkAvailability() { // set jfr.unsupported.vm to true to test API on an unsupported VM try { - if (SecuritySupport.getBooleanProperty("jfr.unsupported.vm")) { + if (Boolean.getBoolean("jfr.unsupported.vm")) { return false; } } catch (NoClassDefFoundError cnfe) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java index 6d1d5cf7938..7adafce6768 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -64,7 +64,6 @@ final class JVMUpcalls { Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Skipping instrumentation for " + clazz.getName() + " since container support is missing"); return oldBytes; } - EventWriterKey.ensureEventWriterFactory(); EventConfiguration configuration = JVMSupport.getConfiguration(clazz.asSubclass(jdk.internal.event.Event.class)); if (configuration == null) { Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "No event configuration found for " + clazz.getName() + ". Ignoring instrumentation request."); @@ -124,7 +123,6 @@ final class JVMUpcalls { return oldBytes; } } - EventWriterKey.ensureEventWriterFactory(); Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Adding " + (forceInstrumentation ? "forced " : "") + "instrumentation for event type " + eventName + " during initial class load"); byte[] bytes = ei.buildInstrumented(); Bytecode.log(ei.getClassName() + "(" + traceId + ")", bytes); @@ -155,6 +153,8 @@ final class JVMUpcalls { * @return a new thread */ static Thread createRecorderThread(ThreadGroup systemThreadGroup, ClassLoader contextClassLoader) { - return SecuritySupport.createRecorderThread(systemThreadGroup, contextClassLoader); + Thread thread = new Thread(systemThreadGroup, "JFR Recorder Thread"); + thread.setContextClassLoader(contextClassLoader); + return thread; } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataLoader.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataLoader.java index d0b53854752..60db375c876 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataLoader.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -191,7 +191,7 @@ public final class MetadataLoader { public static List createTypes() throws IOException { try (DataInputStream dis = new DataInputStream( - SecuritySupport.getResourceAsStream("/jdk/jfr/internal/types/metadata.bin"))) { + MetadataLoader.class.getResourceAsStream("/jdk/jfr/internal/types/metadata.bin"))) { MetadataLoader ml = new MetadataLoader(dis); return ml.buildTypes(); } catch (Exception e) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java index 49afd0082d8..951142e2493 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -123,7 +123,6 @@ public final class MetadataRepository { } public synchronized void unregister(Class eventClass) { - SecuritySupport.checkRegisterPermission(); EventConfiguration configuration = getConfiguration(eventClass, false); if (configuration != null) { configuration.getPlatformEventType().setRegistered(false); @@ -135,7 +134,6 @@ public final class MetadataRepository { } public synchronized EventType register(Class eventClass, List dynamicAnnotations, List dynamicFields) { - SecuritySupport.checkRegisterPermission(); if (JVM.isExcluded(eventClass)) { // Event classes are marked as excluded during class load // if they override methods in the jdk.jfr.Event class, i.e. commit(). @@ -186,7 +184,7 @@ public final class MetadataRepository { if (cachedEventConfigurationConstructor == null) { var argClasses = new Class[] { EventType.class, EventControl.class}; Constructor c = EventConfiguration.class.getDeclaredConstructor(argClasses); - SecuritySupport.setAccessible(c); + c.setAccessible(true); cachedEventConfigurationConstructor = c; } return cachedEventConfigurationConstructor.newInstance(eventType, ec); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java index d07f1e6cb5e..beeb46e1a60 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -26,8 +26,9 @@ package jdk.jfr.internal; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; -import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.internal.misc.Unsafe; import static java.nio.file.LinkOption.*; @@ -50,7 +51,7 @@ public final class Options { private static long DEFAULT_THREAD_BUFFER_SIZE; private static final int DEFAULT_STACK_DEPTH = 64; private static final long DEFAULT_MAX_CHUNK_SIZE = 12 * 1024 * 1024; - private static final SafePath DEFAULT_DUMP_PATH = null; + private static final Path DEFAULT_DUMP_PATH = null; private static final boolean DEFAULT_PRESERVE_REPOSITORY = false; private static long memorySize; @@ -115,10 +116,10 @@ public final class Options { globalBufferSize = globalBufsize; } - public static synchronized void setDumpPath(SafePath path) throws IOException { + public static synchronized void setDumpPath(Path path) throws IOException { if (path != null) { - if (SecuritySupport.isWritable(path)) { - path = SecuritySupport.toRealPath(path, NOFOLLOW_LINKS); + if (Files.isWritable(path)) { + path = path.toRealPath(NOFOLLOW_LINKS); } else { throw new IOException("Cannot write JFR emergency dump to " + path.toString()); } @@ -126,8 +127,8 @@ public final class Options { JVM.setDumpPath(path == null ? null : path.toString()); } - public static synchronized SafePath getDumpPath() { - return new SafePath(JVM.getDumpPath()); + public static synchronized Path getDumpPath() { + return Path.of(JVM.getDumpPath()); } public static synchronized void setStackDepth(Integer stackTraceDepth) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java index b33a8943042..646c53f8961 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -33,8 +33,7 @@ import static jdk.jfr.internal.LogTag.JFR; import static jdk.jfr.internal.LogTag.JFR_SYSTEM; import java.io.IOException; -import java.security.AccessControlContext; -import java.security.AccessController; +import java.nio.file.Path; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; @@ -46,7 +45,6 @@ import java.util.Map; import java.util.Set; import java.util.Timer; import java.util.TimerTask; -import java.util.concurrent.CopyOnWriteArrayList; import jdk.jfr.FlightRecorder; import jdk.jfr.FlightRecorderListener; @@ -54,8 +52,6 @@ import jdk.jfr.Recording; import jdk.jfr.RecordingState; import jdk.jfr.events.ActiveRecordingEvent; import jdk.jfr.events.ActiveSettingEvent; -import jdk.jfr.internal.SecuritySupport.SafePath; -import jdk.jfr.internal.SecuritySupport.SecureRecorderListener; import jdk.jfr.internal.consumer.EventLog; import jdk.jfr.internal.periodic.PeriodicEvents; import jdk.jfr.internal.util.Utils; @@ -64,7 +60,7 @@ public final class PlatformRecorder { private final ArrayList recordings = new ArrayList<>(); - private static final List changeListeners = new ArrayList<>(); + private static final List changeListeners = new ArrayList<>(); private final Repository repository; private final Thread shutdownHook; @@ -83,25 +79,9 @@ public final class PlatformRecorder { JDKEvents.initialize(); Logger.log(JFR_SYSTEM, INFO, "Registered JDK events"); startDiskMonitor(); - shutdownHook = SecuritySupport.createThreadWitNoPermissions("JFR Shutdown Hook", new ShutdownHook(this)); - SecuritySupport.setUncaughtExceptionHandler(shutdownHook, new ShutdownHook.ExceptionHandler()); - SecuritySupport.registerShutdownHook(shutdownHook); - } - - - private static Timer createTimer() { - try { - List result = new CopyOnWriteArrayList<>(); - Thread t = SecuritySupport.createThreadWitNoPermissions("Permissionless thread", ()-> { - result.add(new Timer("JFR Recording Scheduler", true)); - }); - JVM.exclude(t); - t.start(); - t.join(); - return result.getFirst(); - } catch (InterruptedException e) { - throw new IllegalStateException("Not able to create timer task. " + e.getMessage(), e); - } + shutdownHook = new ShutdownHook(this); + shutdownHook.setUncaughtExceptionHandler(new ShutdownHook.ExceptionHandler()); + Runtime.getRuntime().addShutdownHook(shutdownHook); } public synchronized PlatformRecording newRecording(Map settings) { @@ -138,27 +118,18 @@ public final class PlatformRecorder { } public static synchronized void addListener(FlightRecorderListener changeListener) { - @SuppressWarnings("removal") - AccessControlContext context = AccessController.getContext(); - SecureRecorderListener sl = new SecureRecorderListener(context, changeListener); boolean runInitialized; synchronized (PlatformRecorder.class) { runInitialized = FlightRecorder.isInitialized(); - changeListeners.add(sl); + changeListeners.add(changeListener); } if (runInitialized) { - sl.recorderInitialized(FlightRecorder.getFlightRecorder()); + changeListener.recorderInitialized(FlightRecorder.getFlightRecorder()); } } public static synchronized boolean removeListener(FlightRecorderListener changeListener) { - for (SecureRecorderListener s : new ArrayList<>(changeListeners)) { - if (s.getChangeListener() == changeListener) { - changeListeners.remove(s); - return true; - } - } - return false; + return changeListeners.remove(changeListener); } static synchronized List getListeners() { @@ -167,7 +138,7 @@ public final class PlatformRecorder { synchronized Timer getTimer() { if (timer == null) { - timer = createTimer(); + timer = new Timer("JFR Recording Scheduler", true); } return timer; } @@ -366,7 +337,7 @@ public final class PlatformRecorder { } private Instant dumpMemoryToDestination(PlatformRecording recording) { - WriteableUserPath dest = recording.getDestination(); + WriteablePath dest = recording.getDestination(); if (dest != null) { Instant t = MetadataRepository.getInstance().setOutput(dest.getRealPathText()); recording.clearDestination(); @@ -441,8 +412,8 @@ public final class PlatformRecorder { } private void startDiskMonitor() { - Thread t = SecuritySupport.createThreadWitNoPermissions("JFR Periodic Tasks", () -> periodicTask()); - SecuritySupport.setDaemonThread(t, true); + Thread t = new Thread(() -> periodicTask(), "JFR Periodic Tasks"); + t.setDaemon(true); t.start(); } @@ -472,7 +443,7 @@ public final class PlatformRecorder { if (ActiveRecordingEvent.enabled()) { for (PlatformRecording r : getRecordings()) { if (r.getState() == RecordingState.RUNNING && r.shouldWriteMetadataEvent()) { - WriteableUserPath path = r.getDestination(); + WriteablePath path = r.getDestination(); Duration age = r.getMaxAge(); Duration flush = r.getFlushInterval(); Long size = r.getMaxSize(); @@ -519,7 +490,7 @@ public final class PlatformRecorder { wait = Math.min(minDelta, Options.getWaitInterval()); } catch (Throwable t) { // Catch everything and log, but don't allow it to end the periodic task - Logger.log(JFR_SYSTEM, ERROR, "Error in Periodic task: " + t.getClass().getName()); + Logger.log(JFR_SYSTEM, WARN, "Error in Periodic task: " + t.getMessage()); } finally { takeNap(wait); } @@ -660,7 +631,7 @@ public final class PlatformRecorder { target.setInternalDuration(startTime.until(endTime)); } - public synchronized void migrate(SafePath repo) throws IOException { + public synchronized void migrate(Path repo) throws IOException { // Must set repository while holding recorder lock so // the final chunk in repository gets marked correctly Repository.getRepository().setBasePath(repo); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java index 6014bbbf9d2..025b2878253 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -35,11 +35,8 @@ import java.io.IOException; import java.io.InputStream; import java.nio.channels.FileChannel; import java.nio.file.NoSuchFileException; +import java.nio.file.Path; import java.nio.file.StandardOpenOption; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.time.Duration; import java.time.Instant; import java.time.LocalDateTime; @@ -59,7 +56,6 @@ import jdk.jfr.Configuration; import jdk.jfr.FlightRecorderListener; import jdk.jfr.Recording; import jdk.jfr.RecordingState; -import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.jfr.internal.util.Utils; import jdk.jfr.internal.util.ValueFormatter; @@ -73,12 +69,12 @@ public final class PlatformRecording implements AutoCloseable { private Duration maxAge; private long maxSize; - private WriteableUserPath destination; + private WriteablePath destination; private boolean toDisk = true; private String name; private boolean dumpOnExit; - private SafePath dumpDirectory; + private Path dumpDirectory; // Timestamp information private Instant stopTime; private Instant startTime; @@ -90,8 +86,6 @@ public final class PlatformRecording implements AutoCloseable { private volatile Recording recording; private TimerTask stopTask; private TimerTask startTask; - @SuppressWarnings("removal") - private final AccessControlContext dumpDirectoryControlContext; private boolean shouldWriteActiveRecordingEvent = true; private Duration flushInterval = Duration.ofSeconds(1); private long finalStartChunkNanos = Long.MIN_VALUE; @@ -99,13 +93,6 @@ public final class PlatformRecording implements AutoCloseable { @SuppressWarnings("removal") PlatformRecording(PlatformRecorder recorder, long id) { - // Typically the access control context is taken - // when you call dump(Path) or setDestination(Path), - // but if no destination is set and the filename is auto-generated, - // the control context of the recording is taken when the - // Recording object is constructed. This works well for - // -XX:StartFlightRecording and JFR.dump - this.dumpDirectoryControlContext = AccessController.getContext(); this.id = id; this.recorder = recorder; this.name = String.valueOf(id); @@ -175,7 +162,7 @@ public final class PlatformRecording implements AutoCloseable { Logger.log(LogTag.JFR, LogLevel.INFO, "Stopped recording \"" + getName() + "\" (" + getId() + ")" + endText); newState = getState(); } - WriteableUserPath dest = getDestination(); + WriteablePath dest = getDestination(); if (dest == null && dumpDirectory != null) { dest = makeDumpPath(); } @@ -195,30 +182,18 @@ public final class PlatformRecording implements AutoCloseable { return true; } - @SuppressWarnings("removal") - public WriteableUserPath makeDumpPath() { + public WriteablePath makeDumpPath() { try { String name = JVMSupport.makeFilename(getRecording()); - return AccessController.doPrivileged(new PrivilegedExceptionAction() { - @Override - public WriteableUserPath run() throws Exception { - SafePath p = dumpDirectory; - if (p == null) { - p = new SafePath("."); - } - return new WriteableUserPath(p.toPath().resolve(name)); - } - }, dumpDirectoryControlContext); - } catch (PrivilegedActionException e) { - Throwable t = e.getCause(); - if (t instanceof SecurityException) { - Logger.log(LogTag.JFR, LogLevel.WARN, "Not allowed to create dump path for recording " + recording.getId() + " on exit."); + Path p = dumpDirectory; + if (p == null) { + p = Path.of("."); } - if (t instanceof IOException) { - Logger.log(LogTag.JFR, LogLevel.WARN, "Could not dump " + recording.getId() + " on exit."); - } - return null; + return new WriteablePath(p.resolve(name)); + } catch (IOException e) { + Logger.log(LogTag.JFR, LogLevel.WARN, "Could not dump " + recording.getId() + " on exit. " + e.getMessage()); } + return null; } @@ -422,14 +397,16 @@ public final class PlatformRecording implements AutoCloseable { } } - public void setDestination(WriteableUserPath userSuppliedPath) throws IOException { + public void setDestination(WriteablePath destination) throws IOException { synchronized (recorder) { - checkSetDestination(userSuppliedPath); - this.destination = userSuppliedPath; + checkSetDestination(destination); + this.destination = destination; } } - public void checkSetDestination(WriteableUserPath userSuppliedPath) throws IOException { + public void checkSetDestination(WriteablePath writeablePath) throws IOException { + // The writeablePath argument is not checked. It's sufficient that an instance has + // been created. synchronized (recorder) { if (Utils.isState(getState(), RecordingState.STOPPED, RecordingState.CLOSED)) { throw new IllegalStateException("Destination can't be set on a recording that has been stopped/closed"); @@ -437,7 +414,7 @@ public final class PlatformRecording implements AutoCloseable { } } - public WriteableUserPath getDestination() { + public WriteablePath getDestination() { synchronized (recorder) { return destination; } @@ -707,8 +684,7 @@ public final class PlatformRecording implements AutoCloseable { try { stop("End of duration reached"); } catch (Throwable t) { - // Prevent malicious user to propagate exception callback in the wrong context - Logger.log(LogTag.JFR, LogLevel.ERROR, "Could not stop recording."); + Logger.log(LogTag.JFR, LogLevel.ERROR, "Could not stop recording. " + t.getMessage()); } } }; @@ -737,37 +713,34 @@ public final class PlatformRecording implements AutoCloseable { } // Dump running and stopped recordings - public void dump(WriteableUserPath writeableUserPath) throws IOException { + public void dump(WriteablePath writeablePath) throws IOException { synchronized (recorder) { try(PlatformRecording p = newSnapshotClone("Dumped by user", null)) { - p.dumpStopped(writeableUserPath); + p.dumpStopped(writeablePath); } } } - public void dumpStopped(WriteableUserPath userPath) throws IOException { + public void dumpStopped(WriteablePath path) throws IOException { synchronized (recorder) { - transferChunksWithRetry(userPath); + transferChunksWithRetry(path); } } - private void transferChunksWithRetry(WriteableUserPath userPath) throws IOException { - userPath.doPrivilegedIO(() -> { - try { - transferChunks(userPath); - } catch (NoSuchFileException nsfe) { - Logger.log(LogTag.JFR, LogLevel.ERROR, "Missing chunkfile when writing recording \"" + name + "\" (" + id + ") to " + userPath.getRealPathText() + "."); - // if one chunkfile was missing, its likely more are missing - removeNonExistantPaths(); - // and try the transfer again - transferChunks(userPath); - } - return null; - }); + private void transferChunksWithRetry(WriteablePath path) throws IOException { + try { + transferChunks(path); + } catch (NoSuchFileException nsfe) { + Logger.log(LogTag.JFR, LogLevel.ERROR, "Missing chunkfile when writing recording \"" + name + "\" (" + id + ") to " + path.getRealPathText() + "."); + // if one chunkfile was missing, its likely more are missing + removeNonExistantPaths(); + // and try the transfer again + transferChunks(path); + } } - private void transferChunks(WriteableUserPath userPath) throws IOException { - try (ChunksChannel cc = new ChunksChannel(chunks); FileChannel fc = FileChannel.open(userPath.getReal(), StandardOpenOption.WRITE, StandardOpenOption.APPEND)) { + private void transferChunks(WriteablePath path) throws IOException { + try (ChunksChannel cc = new ChunksChannel(chunks); FileChannel fc = FileChannel.open(path.getReal(), StandardOpenOption.WRITE, StandardOpenOption.APPEND)) { long bytes = cc.transferTo(fc); Logger.log(LogTag.JFR, LogLevel.INFO, "Transferred " + bytes + " bytes from the disk repository"); // No need to force if no data was transferred, which avoids IOException when device is /dev/null @@ -859,7 +832,7 @@ public final class PlatformRecording implements AutoCloseable { *

* Only to be used by DCmdStart. */ - public void setDumpDirectory(SafePath directory) { + public void setDumpDirectory(Path directory) { this.dumpDirectory = directory; } @@ -913,7 +886,7 @@ public final class PlatformRecording implements AutoCloseable { } - public void removePath(SafePath path) { + public void removePath(Path path) { synchronized (recorder) { Iterator it = chunks.iterator(); while (it.hasNext()) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java index dd28a27884f..e9945f71158 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -25,7 +25,6 @@ package jdk.jfr.internal; -import java.security.AccessControlContext; import java.util.List; import java.util.Map; @@ -35,7 +34,6 @@ import jdk.jfr.EventSettings; import jdk.jfr.EventType; import jdk.jfr.FlightRecorderPermission; import jdk.jfr.Recording; -import jdk.jfr.SettingControl; import jdk.jfr.SettingDescriptor; import jdk.jfr.ValueDescriptor; import jdk.jfr.internal.management.EventSettingsModifier; @@ -60,7 +58,7 @@ public abstract class PrivateAccess { // Will trigger // FlightRecorderPermission. // which will call PrivateAccess.setPrivateAccess - new FlightRecorderPermission(SecuritySupport.REGISTER_EVENT); + new FlightRecorderPermission("accessFlightRecorder"); } return instance; } @@ -99,9 +97,6 @@ public abstract class PrivateAccess { public abstract PlatformRecorder getPlatformRecorder(); - @SuppressWarnings("removal") - public abstract AccessControlContext getContext(SettingControl sc); - public abstract EventSettings newEventSettings(EventSettingsModifier esm); public abstract boolean isVisible(EventType t); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/Repository.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/Repository.java index ff09d58a9c0..f2cd873790a 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Repository.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Repository.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -26,6 +26,7 @@ package jdk.jfr.internal; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.time.DateTimeException; import java.time.LocalDateTime; @@ -33,20 +34,20 @@ import java.time.ZoneOffset; import java.util.HashSet; import java.util.Set; -import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.jfr.internal.management.ChunkFilename; import jdk.jfr.internal.util.ValueFormatter; +import jdk.jfr.internal.util.DirectoryCleaner; +import jdk.jfr.internal.util.Utils; public final class Repository { + private static final Path JAVA_IO_TMPDIR = Utils.getPathInProperty("java.io.tmpdir", null); private static final int MAX_REPO_CREATION_RETRIES = 1000; private static final Repository instance = new Repository(); - private static final String JFR_REPOSITORY_LOCATION_PROPERTY = "jdk.jfr.repository"; - - private final Set cleanupDirectories = new HashSet<>(); - private SafePath baseLocation; - private SafePath repository; + private final Set cleanupDirectories = new HashSet<>(); + private Path baseLocation; + private Path repository; private ChunkFilename chunkFilename; private Repository() { @@ -56,7 +57,7 @@ public final class Repository { return instance; } - public synchronized void setBasePath(SafePath baseLocation) throws IOException { + public synchronized void setBasePath(Path baseLocation) throws IOException { if(baseLocation.equals(this.baseLocation)) { Logger.log(LogTag.JFR, LogLevel.INFO, "Same base repository path " + baseLocation.toString() + " is set"); return; @@ -68,7 +69,7 @@ public final class Repository { try { // Remove so we don't "leak" repositories, if JFR is never started // and shutdown hook not added. - SecuritySupport.delete(repository); + Files.delete(repository); } catch (IOException ioe) { Logger.log(LogTag.JFR, LogLevel.INFO, "Could not delete disk repository " + repository); } @@ -77,25 +78,25 @@ public final class Repository { public synchronized void ensureRepository() throws IOException { if (baseLocation == null) { - setBasePath(SecuritySupport.JAVA_IO_TMPDIR); + setBasePath(JAVA_IO_TMPDIR); } } synchronized RepositoryChunk newChunk() { LocalDateTime timestamp = timestamp(); try { - if (!SecuritySupport.existDirectory(repository)) { + if (!Files.exists(repository)) { this.repository = createRepository(baseLocation); JVM.setRepositoryLocation(repository.toString()); - SecuritySupport.setProperty(JFR_REPOSITORY_LOCATION_PROPERTY, repository.toString()); + System.setProperty(JFR_REPOSITORY_LOCATION_PROPERTY, repository.toString()); cleanupDirectories.add(repository); chunkFilename = null; } if (chunkFilename == null) { - chunkFilename = ChunkFilename.newPriviliged(repository.toPath()); + chunkFilename = new ChunkFilename(repository); } String filename = chunkFilename.next(timestamp); - return new RepositoryChunk(new SafePath(filename)); + return new RepositoryChunk(Path.of(filename)); } catch (Exception e) { String errorMsg = String.format("Could not create chunk in repository %s, %s: %s", repository, e.getClass(), e.getMessage()); Logger.log(LogTag.JFR, LogLevel.ERROR, errorMsg); @@ -113,16 +114,16 @@ public final class Repository { } } - private static SafePath createRepository(SafePath basePath) throws IOException { - SafePath canonicalBaseRepositoryPath = createRealBasePath(basePath); - SafePath f = null; + private static Path createRepository(Path basePath) throws IOException { + Path canonicalBaseRepositoryPath = createRealBasePath(basePath); + Path f = null; String basename = ValueFormatter.formatDateTime(timestamp()) + "_" + JVM.getPid(); String name = basename; int i = 0; for (; i < MAX_REPO_CREATION_RETRIES; i++) { - f = new SafePath(canonicalBaseRepositoryPath.toPath().resolve(name)); + f = canonicalBaseRepositoryPath.resolve(name); if (tryToUseAsRepository(f)) { break; } @@ -132,41 +133,36 @@ public final class Repository { if (i == MAX_REPO_CREATION_RETRIES) { throw new IOException("Unable to create JFR repository directory using base location (" + basePath + ")"); } - return SecuritySupport.toRealPath(f); + return f.toRealPath(); } - private static SafePath createRealBasePath(SafePath safePath) throws IOException { - if (SecuritySupport.exists(safePath)) { - if (!SecuritySupport.isWritable(safePath)) { - throw new IOException("JFR repository directory (" + safePath.toString() + ") exists, but isn't writable"); + private static Path createRealBasePath(Path path) throws IOException { + if (Files.exists(path)) { + if (!Files.isWritable(path)) { + throw new IOException("JFR repository directory (" + path.toString() + ") exists, but isn't writable"); } - return SecuritySupport.toRealPath(safePath); + return path.toRealPath(); } - SafePath p = SecuritySupport.createDirectories(safePath); - return SecuritySupport.toRealPath(p); + return Files.createDirectories(path).toRealPath(); } - private static boolean tryToUseAsRepository(final SafePath path) { - Path parent = path.toPath().getParent(); + private static boolean tryToUseAsRepository(Path path) { + Path parent = path.getParent(); if (parent == null) { return false; } try { - try { - SecuritySupport.createDirectories(path); - } catch (Exception e) { - // file already existed or some other problem occurred - } - if (!SecuritySupport.exists(path)) { - return false; - } - if (!SecuritySupport.isDirectory(path)) { - return false; - } - return true; - } catch (IOException io) { + Files.createDirectories(path); + } catch (Exception e) { + // file already existed or some other problem occurred + } + if (!Files.exists(path)) { return false; } + if (!Files.isDirectory(path)) { + return false; + } + return true; } synchronized void clear() { @@ -174,9 +170,9 @@ public final class Repository { return; } - for (SafePath p : cleanupDirectories) { + for (Path p : cleanupDirectories) { try { - SecuritySupport.clearDirectory(p); + DirectoryCleaner.clear(p); Logger.log(LogTag.JFR, LogLevel.INFO, "Removed repository " + p); } catch (IOException e) { Logger.log(LogTag.JFR, LogLevel.INFO, "Repository " + p + " could not be removed at shutdown: " + e.getMessage()); @@ -184,11 +180,11 @@ public final class Repository { } } - public synchronized SafePath getRepositoryPath() { + public synchronized Path getRepositoryPath() { return repository; } - public synchronized SafePath getBaseLocation() { + public synchronized Path getBaseLocation() { return baseLocation; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java index e46b6020d5d..6507c5f6668 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -27,12 +27,14 @@ package jdk.jfr.internal; import java.io.IOException; import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; import java.time.Instant; import java.util.Comparator; -import jdk.jfr.internal.SecuritySupport.SafePath; - public final class RepositoryChunk { static final Comparator END_TIME_COMPARATOR = new Comparator() { @@ -42,7 +44,7 @@ public final class RepositoryChunk { } }; - private final SafePath chunkFile; + private final Path chunkFile; private final RandomAccessFile unFinishedRAF; private Instant endTime = null; // unfinished @@ -50,15 +52,15 @@ public final class RepositoryChunk { private int refCount = 1; private long size; - RepositoryChunk(SafePath path) throws Exception { + RepositoryChunk(Path path) throws Exception { this.chunkFile = path; - this.unFinishedRAF = SecuritySupport.createRandomAccessFile(chunkFile); + this.unFinishedRAF = new RandomAccessFile(path.toFile(), "rw"); } boolean finish(Instant endTime) { try { unFinishedRAF.close(); - size = SecuritySupport.getFileSize(chunkFile); + size = Files.size(chunkFile); this.endTime = endTime; if (Logger.shouldLog(LogTag.JFR_SYSTEM, LogLevel.DEBUG)) { Logger.log(LogTag.JFR_SYSTEM, LogLevel.DEBUG, "Chunk finished: " + chunkFile); @@ -89,9 +91,9 @@ public final class RepositoryChunk { return endTime; } - private void delete(SafePath f) { + private void delete(Path f) { try { - SecuritySupport.delete(f); + Files.delete(f); if (Logger.shouldLog(LogTag.JFR, LogLevel.DEBUG)) { Logger.log(LogTag.JFR, LogLevel.DEBUG, "Repository chunk " + f + " deleted"); } @@ -153,7 +155,7 @@ public final class RepositoryChunk { if (!isFinished()) { throw new IOException("Chunk not finished"); } - return ((SecuritySupport.newFileChannelToRead(chunkFile))); + return FileChannel.open(chunkFile, StandardOpenOption.READ); } public boolean inInterval(Instant startTime, Instant endTime) { @@ -166,23 +168,19 @@ public final class RepositoryChunk { return true; } - public SafePath getFile() { + public Path getFile() { return chunkFile; } public long getCurrentFileSize() { try { - return SecuritySupport.getFileSize(chunkFile); + return Files.size(chunkFile); } catch (IOException e) { return 0L; } } boolean isMissingFile() { - try { - return !SecuritySupport.exists(chunkFile); - } catch (IOException ioe) { - return true; - } + return !Files.exists(chunkFile); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java index 7398b6a91b7..98bc0c86bfa 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -25,63 +25,13 @@ package jdk.jfr.internal; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; -import java.io.Reader; import java.lang.invoke.MethodHandles; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.lang.reflect.ReflectPermission; -import java.nio.channels.FileChannel; -import java.nio.channels.ReadableByteChannel; -import java.nio.file.DirectoryStream; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.LinkOption; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardOpenOption; -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.FileTime; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.Permission; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.PropertyPermission; -import java.util.concurrent.Callable; - import jdk.internal.module.Modules; import jdk.jfr.Event; -import jdk.jfr.FlightRecorder; -import jdk.jfr.FlightRecorderListener; -import jdk.jfr.FlightRecorderPermission; -import jdk.jfr.Recording; -import jdk.jfr.internal.consumer.FileAccess; -/** - * Contains JFR code that does - * {@link AccessController#doPrivileged(PrivilegedAction)} - */ public final class SecuritySupport { - private static final String EVENTS_PACKAGE_NAME = "jdk.jfr.events"; - private static final String EVENT_PACKAGE_NAME = "jdk.jfr.internal.event"; - - public static final String REGISTER_EVENT = "registerEvent"; - public static final String ACCESS_FLIGHT_RECORDER = "accessFlightRecorder"; - private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); private static final Module JFR_MODULE = Event.class.getModule(); - public static final SafePath JFC_DIRECTORY = getPathInProperty("java.home", "lib/jfr"); - public static final FileAccess PRIVILEGED = new Privileged(); - static final SafePath JAVA_IO_TMPDIR = getPathInProperty("java.io.tmpdir", null); + private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); static { // ensure module java.base can read module jdk.jfr as early as possible @@ -90,215 +40,6 @@ public final class SecuritySupport { addEventsExport(Object.class); } - static final class SecureRecorderListener implements FlightRecorderListener { - - @SuppressWarnings("removal") - private final AccessControlContext context; - private final FlightRecorderListener changeListener; - - SecureRecorderListener(@SuppressWarnings("removal") AccessControlContext context, FlightRecorderListener changeListener) { - this.context = Objects.requireNonNull(context); - this.changeListener = Objects.requireNonNull(changeListener); - } - - @SuppressWarnings("removal") - @Override - public void recordingStateChanged(Recording recording) { - AccessController.doPrivileged((PrivilegedAction) () -> { - try { - changeListener.recordingStateChanged(recording); - } catch (Throwable t) { - // Prevent malicious user to propagate exception callback in the wrong context - Logger.log(LogTag.JFR, LogLevel.WARN, "Unexpected exception in listener " + changeListener.getClass()+ " at recording state change"); - } - return null; - }, context); - } - - @SuppressWarnings("removal") - @Override - public void recorderInitialized(FlightRecorder recorder) { - AccessController.doPrivileged((PrivilegedAction) () -> { - try { - changeListener.recorderInitialized(recorder); - } catch (Throwable t) { - // Prevent malicious user to propagate exception callback in the wrong context - Logger.log(LogTag.JFR, LogLevel.WARN, "Unexpected exception in listener " + changeListener.getClass()+ " when initializing FlightRecorder"); - } - return null; - }, context); - } - - public FlightRecorderListener getChangeListener() { - return changeListener; - } - } - - private static final class DirectoryCleaner extends SimpleFileVisitor { - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException { - Files.delete(path); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - if (exc != null) { - throw exc; - } - Files.delete(dir); - return FileVisitResult.CONTINUE; - } - } - - /** - * Path created by the default file provider, and not - * a malicious provider. - * - */ - public static final class SafePath implements Comparable { - private final Path path; - private final String text; - - public SafePath(Path p) { - // sanitize - text = p.toString(); - path = Paths.get(text); - } - - public SafePath(String path) { - this(Paths.get(path)); - } - - public Path toPath() { - return path; - } - - public File toFile() { - return path.toFile(); - } - - @Override - public String toString() { - return text; - } - - @Override - public int compareTo(SafePath that) { - return that.text.compareTo(this.text); - } - - @Override - public boolean equals(Object other) { - if(other != null && other instanceof SafePath s){ - return this.toPath().equals(s.toPath()); - } - return false; - } - - @Override - public int hashCode() { - return this.toPath().hashCode(); - } - } - - private interface RunnableWithCheckedException { - public void run() throws Exception; - } - - private interface CallableWithoutCheckException { - public T call(); - } - - public static void checkAccessFlightRecorder() throws SecurityException { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new FlightRecorderPermission(ACCESS_FLIGHT_RECORDER)); - } - } - - public static void checkRegisterPermission() throws SecurityException { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new FlightRecorderPermission(REGISTER_EVENT)); - } - } - - @SuppressWarnings("removal") - private static U doPrivilegedIOWithReturn(Callable function) throws IOException { - try { - return AccessController.doPrivileged(new PrivilegedExceptionAction() { - @Override - public U run() throws Exception { - return function.call(); - } - }, null); - } catch (PrivilegedActionException e) { - Throwable t = e.getCause(); - if (t instanceof IOException) { - throw (IOException) t; - } - throw new IOException("Unexpected error during I/O operation. " + t.getMessage(), t); - } - } - - private static void doPriviligedIO(RunnableWithCheckedException function) throws IOException { - doPrivilegedIOWithReturn(() -> { - function.run(); - return null; - }); - } - - @SuppressWarnings("removal") - private static void doPrivileged(Runnable function, Permission... perms) { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - function.run(); - return null; - } - }, null, perms); - } - - @SuppressWarnings("removal") - private static void doPrivileged(Runnable function) { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - function.run(); - return null; - } - }); - } - - @SuppressWarnings("removal") - private static T doPrivilegedWithReturn(CallableWithoutCheckException function, Permission... perms) { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public T run() { - return function.call(); - } - }, null, perms); - } - - public static List getPredefinedJFCFiles() { - List list = new ArrayList<>(); - try (var ds = doPrivilegedIOWithReturn(() -> Files.newDirectoryStream(JFC_DIRECTORY.toPath()))) { - for (Path path : ds) { - SafePath s = new SafePath(path); - String text = s.toString(); - if (text.endsWith(".jfc") && !SecuritySupport.isDirectory(s)) { - list.add(s); - } - } - } catch (IOException ioe) { - Logger.log(LogTag.JFR, LogLevel.WARN, "Could not access .jfc-files in " + JFC_DIRECTORY + ", " + ioe.getMessage()); - } - return list; - } - static void makeVisibleToJFR(Class clazz) { Module classModule = clazz.getModule(); Modules.addReads(JFR_MODULE, classModule); @@ -314,213 +55,31 @@ public final class SecuritySupport { * (for EventConfiguration and EventWriter) */ static void addInternalEventExport(Class clazz) { - Modules.addExports(JFR_MODULE, EVENT_PACKAGE_NAME, clazz.getModule()); + Modules.addExports(JFR_MODULE, "jdk.jfr.internal.event", clazz.getModule()); } static void addEventsExport(Class clazz) { - Modules.addExports(JFR_MODULE, EVENTS_PACKAGE_NAME, clazz.getModule()); + Modules.addExports(JFR_MODULE, "jdk.jfr.events", clazz.getModule()); } static void addReadEdge(Class clazz) { Modules.addReads(clazz.getModule(), JFR_MODULE); } - public static void registerEvent(Class eventClass) { - doPrivileged(() -> MetadataRepository.getInstance().register(eventClass), new FlightRecorderPermission(REGISTER_EVENT)); - } - - public static void setProperty(String propertyName, String value) { - doPrivileged(() -> System.setProperty(propertyName, value), new PropertyPermission(propertyName, "write")); - } - - static boolean getBooleanProperty(String propertyName) { - return doPrivilegedWithReturn(() -> Boolean.getBoolean(propertyName), new PropertyPermission(propertyName, "read")); - } - - private static SafePath getPathInProperty(String prop, String subPath) { - return doPrivilegedWithReturn(() -> { - String path = System.getProperty(prop); - if (path == null) { - return null; - } - File file = subPath == null ? new File(path) : new File(path, subPath); - return new SafePath(file.getAbsolutePath()); - }, new PropertyPermission("*", "read")); - } - - // Called by JVM during initialization of JFR - static Thread createRecorderThread(ThreadGroup systemThreadGroup, ClassLoader contextClassLoader) { - // The thread should have permission = new Permission[0], and not "modifyThreadGroup" and "modifyThread" on the stack, - // but it's hard circumvent if we are going to pass in system thread group in the constructor - Thread thread = doPrivilegedWithReturn(() -> new Thread(systemThreadGroup, "JFR Recorder Thread"), new RuntimePermission("modifyThreadGroup"), new RuntimePermission("modifyThread")); - doPrivileged(() -> thread.setContextClassLoader(contextClassLoader), new RuntimePermission("setContextClassLoader"), new RuntimePermission("modifyThread")); - return thread; - } - - static void registerShutdownHook(Thread shutdownHook) { - doPrivileged(() -> Runtime.getRuntime().addShutdownHook(shutdownHook), new RuntimePermission("shutdownHooks")); - } - - static void setUncaughtExceptionHandler(Thread thread, Thread.UncaughtExceptionHandler eh) { - doPrivileged(() -> thread.setUncaughtExceptionHandler(eh), new RuntimePermission("modifyThread")); - } - - static void clearDirectory(SafePath safePath) throws IOException { - doPriviligedIO(() -> Files.walkFileTree(safePath.toPath(), new DirectoryCleaner())); - } - - static SafePath toRealPath(SafePath safePath, LinkOption... options) throws IOException { - return new SafePath(doPrivilegedIOWithReturn(() -> safePath.toPath().toRealPath(options))); - } - - static boolean existDirectory(SafePath directory) throws IOException { - return doPrivilegedIOWithReturn(() -> Files.exists(directory.toPath())); - } - - static RandomAccessFile createRandomAccessFile(SafePath path) throws Exception { - return doPrivilegedIOWithReturn(() -> new RandomAccessFile(path.toPath().toFile(), "rw")); - } - - public static InputStream newFileInputStream(SafePath safePath) throws IOException { - return doPrivilegedIOWithReturn(() -> Files.newInputStream(safePath.toPath())); - } - - public static long getFileSize(SafePath safePath) throws IOException { - return doPrivilegedIOWithReturn(() -> Files.size(safePath.toPath())); - } - - static SafePath createDirectories(SafePath safePath) throws IOException { - Path p = doPrivilegedIOWithReturn(() -> Files.createDirectories(safePath.toPath())); - return new SafePath(p); - } - - public static boolean exists(SafePath safePath) throws IOException { - // Files.exist(path) is allocation intensive - return doPrivilegedIOWithReturn(() -> safePath.toPath().toFile().exists()); - } - - public static boolean isDirectory(SafePath safePath) throws IOException { - return doPrivilegedIOWithReturn(() -> Files.isDirectory(safePath.toPath())); - } - - static void delete(SafePath localPath) throws IOException { - doPriviligedIO(() -> Files.delete(localPath.toPath())); - } - - static boolean isWritable(SafePath safePath) throws IOException { - return doPrivilegedIOWithReturn(() -> Files.isWritable(safePath.toPath())); - } - - static ReadableByteChannel newFileChannelToRead(SafePath safePath) throws IOException { - return doPrivilegedIOWithReturn(() -> FileChannel.open(safePath.toPath(), StandardOpenOption.READ)); - } - - public static InputStream getResourceAsStream(String name) throws IOException { - return doPrivilegedIOWithReturn(() -> SecuritySupport.class.getResourceAsStream(name)); - } - - public static Reader newFileReader(SafePath safePath) throws FileNotFoundException, IOException { - return doPrivilegedIOWithReturn(() -> Files.newBufferedReader(safePath.toPath())); - } - - static void setAccessible(Method method) { - doPrivileged(() -> method.setAccessible(true), new ReflectPermission("suppressAccessChecks")); - } - - static void setAccessible(Constructor constructor) { - doPrivileged(() -> constructor.setAccessible(true), new ReflectPermission("suppressAccessChecks")); - } - - @SuppressWarnings("removal") public static void ensureClassIsInitialized(Class clazz) { try { - MethodHandles.Lookup lookup; - if (System.getSecurityManager() == null) { - lookup = MethodHandles.privateLookupIn(clazz, LOOKUP); - } else { - lookup = AccessController.doPrivileged(new PrivilegedExceptionAction<>() { - @Override - public MethodHandles.Lookup run() throws IllegalAccessException { - return MethodHandles.privateLookupIn(clazz, LOOKUP); - } - }, null, new ReflectPermission("suppressAccessChecks")); - } + MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(clazz, LOOKUP); lookup.ensureInitialized(clazz); } catch (IllegalAccessException e) { throw new InternalError(e); - } catch (PrivilegedActionException e) { - throw new InternalError(e.getCause()); } } - @SuppressWarnings("removal") static Class defineClass(Class lookupClass, byte[] bytes) { - return AccessController.doPrivileged(new PrivilegedAction>() { - @Override - public Class run() { - try { - return MethodHandles.privateLookupIn(lookupClass, LOOKUP).defineClass(bytes); - } catch (IllegalAccessException e) { - throw new InternalError(e); - } - } - }); - } - - public static Thread createThreadWitNoPermissions(String threadName, Runnable runnable) { - return doPrivilegedWithReturn(() -> new Thread(runnable, threadName), new Permission[0]); - } - - public static void setDaemonThread(Thread t, boolean daemon) { - doPrivileged(()-> t.setDaemon(daemon), new RuntimePermission("modifyThread")); - } - - public static SafePath getAbsolutePath(SafePath path) throws IOException { - return new SafePath(doPrivilegedIOWithReturn((()-> path.toPath().toAbsolutePath()))); - } - - private static final class Privileged extends FileAccess { - @Override - public RandomAccessFile openRAF(File f, String mode) throws IOException { - return doPrivilegedIOWithReturn( () -> new RandomAccessFile(f, mode)); - } - - @Override - public DirectoryStream newDirectoryStream(Path directory) throws IOException { - return doPrivilegedIOWithReturn( () -> Files.newDirectoryStream(directory)); - } - - @Override - public String getAbsolutePath(File f) throws IOException { - return doPrivilegedIOWithReturn( () -> f.getAbsolutePath()); - } - @Override - public long length(File f) throws IOException { - return doPrivilegedIOWithReturn( () -> f.length()); - } - - @Override - public long fileSize(Path p) throws IOException { - return doPrivilegedIOWithReturn( () -> Files.size(p)); - } - - @Override - public boolean exists(Path p) throws IOException { - return doPrivilegedIOWithReturn( () -> Files.exists(p)); - } - - @Override - public boolean isDirectory(Path p) { - return doPrivilegedWithReturn( () -> Files.isDirectory(p)); - } - - @Override - public FileTime getLastModified(Path p) throws IOException { - // Timestamp only needed when examining repository for other JVMs, - // in which case an unprivileged mode should be used. - throw new InternalError("Should not reach here"); + try { + return MethodHandles.privateLookupIn(lookupClass, LOOKUP).defineClass(bytes); + } catch (IllegalAccessException e) { + throw new InternalError(e); } } - - } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/ShutdownHook.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/ShutdownHook.java index 8375dab0bcc..ef9e5d53bf9 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/ShutdownHook.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/ShutdownHook.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -25,22 +25,18 @@ package jdk.jfr.internal; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; - import jdk.jfr.RecordingState; /** * Class responsible for dumping recordings on exit * */ -final class ShutdownHook implements Runnable { +final class ShutdownHook extends Thread { private final PlatformRecorder recorder; Object tlabDummyObject; ShutdownHook(PlatformRecorder recorder) { + super("JFR Shutdown Hook"); this.recorder = recorder; } @@ -61,7 +57,7 @@ final class ShutdownHook implements Runnable { private void dump(PlatformRecording recording) { try { - WriteableUserPath dest = recording.getDestination(); + WriteablePath dest = recording.getDestination(); if (dest == null) { dest = recording.makeDumpPath(); recording.setDestination(dest); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java index 350bf55ccd4..bf26294ef57 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -189,7 +189,7 @@ public final class TypeLibrary { Modules.addExports(proxyModule, proxyPackage, jfrModule); } } - SecuritySupport.setAccessible(m); + m.setAccessible(true); try { return m.invoke(annotation, new Object[0]); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/JDKEventTask.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/WriteablePath.java similarity index 52% rename from src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/JDKEventTask.java rename to src/jdk.jfr/share/classes/jdk/jfr/internal/WriteablePath.java index a891b1c3775..5f3672d5d4c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/JDKEventTask.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/WriteablePath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -22,34 +22,42 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.jfr.internal.periodic; -import jdk.internal.event.Event; -import jdk.jfr.internal.util.Utils; +package jdk.jfr.internal; -/** - * Periodic task that runs trusted code that doesn't require an access control - * context. - *

- * This class can be removed once the Security Manager is no longer supported. - */ -final class JDKEventTask extends JavaEventTask { +import java.io.BufferedWriter; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; - public JDKEventTask(Class eventClass, Runnable runnable) { - super(eventClass, runnable); - if (!getEventType().isJDK()) { - throw new InternalError("Must be a JDK event"); - } - if (!Utils.isJDKClass(eventClass)) { - throw new SecurityException("Periodic task can only be registered for event classes that belongs to the JDK"); - } - if (!Utils.isJDKClass(runnable.getClass())) { - throw new SecurityException("Runnable class must belong to the JDK"); +public final class WriteablePath { + private final Path path; + private final Path real; + + public WriteablePath(Path path) throws IOException { + // verify that the path is writeable + if (Files.exists(path) && !Files.isWritable(path)) { + // throw same type of exception as FileOutputStream + // constructor, if file can't be opened. + throw new FileNotFoundException("Could not write to file: " + path.toAbsolutePath()); } + // will throw if non-writeable + BufferedWriter fw = Files.newBufferedWriter(path); + fw.close(); + this.path = path; + this.real = path.toRealPath(); } - @Override - public void execute(long timestamp, PeriodicType periodicType) { - getRunnable().run(); + public Path getPath() { + return path; + } + + public Path getReal() { + return real; + } + + public String getRealPathText() { + return real.toString(); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/WriteableUserPath.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/WriteableUserPath.java deleted file mode 100644 index b53ff48d606..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/WriteableUserPath.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2016, 2022, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package jdk.jfr.internal; - -import java.io.BufferedWriter; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedExceptionAction; -import java.util.concurrent.Callable; - -/** - * Purpose of this class is to simplify analysis of security risks. - *

- * Paths in the public API should be wrapped in this class so we - * at all time know what kind of paths we are dealing with. - *

- * A user supplied path must never be used in an unsafe context, such as a - * shutdown hook or any other thread created by JFR. - *

- * All operation using this path must happen in {@link #doPrivilegedIO(Callable)} - */ -public final class WriteableUserPath { - @SuppressWarnings("removal") - private final AccessControlContext controlContext; - private final Path original; - private final Path real; - private final String realPathText; - private final String originalText; - - // Not to ensure security, but to help - // against programming errors - private volatile boolean inPrivileged; - - @SuppressWarnings("removal") - public WriteableUserPath(Path path) throws IOException { - controlContext = AccessController.getContext(); - // verify that the path is writeable - if (Files.exists(path) && !Files.isWritable(path)) { - // throw same type of exception as FileOutputStream - // constructor, if file can't be opened. - throw new FileNotFoundException("Could not write to file: " + path.toAbsolutePath()); - } - // will throw if non-writeable - BufferedWriter fw = Files.newBufferedWriter(path); - fw.close(); - this.original = path; - this.originalText = path.toString(); - this.real = path.toRealPath(); - this.realPathText = real.toString(); - } - - /** - * Returns a potentially malicious path where the user may have implemented - * their own version of Path. This method should never be called in an - * unsafe context and the Path value should never be passed along to other - * methods. - * - * @return path from a potentially malicious user - */ - public Path getPotentiallyMaliciousOriginal() { - return original; - } - - /** - * Returns a string representation of the real path. - * - * @return path as text - */ - public String getRealPathText() { - return realPathText; - } - - /** - * Returns a string representation of the original path. - * - * @return path as text - */ - public String getOriginalText() { - return originalText; - } - - - /** - * Returns a potentially malicious path where the user may have implemented - * their own version of Path. This method should never be called in an - * unsafe context and the Path value should never be passed along to other - * methods. - * - * @return path from a potentially malicious user - */ - public Path getReal() { - if (!inPrivileged) { - throw new InternalError("A user path was accessed outside the context it was supplied in"); - } - return real; - } - - @SuppressWarnings("removal") - public void doPrivilegedIO(Callable function) throws IOException { - try { - inPrivileged = true; - AccessController.doPrivileged(new PrivilegedExceptionAction() { - @Override - public Void run() throws Exception { - function.call(); - return null; - } - }, controlContext); - } catch (Throwable t) { - // prevent malicious user to propagate exception callback - // in the wrong context - Throwable cause = null; - if (System.getSecurityManager() == null) { - cause = t; - } - throw new IOException("Unexpected error during I/O operation", cause); - } finally { - inPrivileged = false; - } - } -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java index cdfc8f017a6..b9994c1e51c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -26,9 +26,6 @@ package jdk.jfr.internal.consumer; import java.io.IOException; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.time.Duration; import java.time.Instant; import java.util.List; @@ -46,7 +43,6 @@ import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.internal.LogLevel; import jdk.jfr.internal.LogTag; import jdk.jfr.internal.Logger; -import jdk.jfr.internal.SecuritySupport; /* * Purpose of this class is to simplify the implementation of @@ -57,8 +53,6 @@ public abstract class AbstractEventStream implements EventStream { private final CountDownLatch terminated = new CountDownLatch(1); private final Runnable flushOperation = () -> dispatcher().runFlushActions(); - @SuppressWarnings("removal") - private final AccessControlContext accessControllerContext; private final StreamConfiguration streamConfiguration = new StreamConfiguration(); private final List configurations; private final ParserState parserState = new ParserState(); @@ -67,8 +61,7 @@ public abstract class AbstractEventStream implements EventStream { private boolean daemon = false; - AbstractEventStream(@SuppressWarnings("removal") AccessControlContext acc, List configurations) throws IOException { - this.accessControllerContext = Objects.requireNonNull(acc); + AbstractEventStream(List configurations) throws IOException { this.configurations = configurations; } @@ -221,22 +214,21 @@ public abstract class AbstractEventStream implements EventStream { public final void startAsync(long startNanos) { startInternal(startNanos); - Runnable r = () -> run(accessControllerContext); - Thread thread = SecuritySupport.createThreadWitNoPermissions(nextThreadName(), r); - SecuritySupport.setDaemonThread(thread, daemon); + Runnable r = () -> execute(); + Thread thread = new Thread(r, nextThreadName()); + thread.setDaemon(daemon); thread.start(); } public final void start(long startNanos) { startInternal(startNanos); - run(accessControllerContext); + execute(); } protected final Runnable getFlushOperation() { return flushOperation; } - protected final void onFlush() { Runnable r = getFlushOperation(); if (r != null) { @@ -276,17 +268,6 @@ public abstract class AbstractEventStream implements EventStream { } } - @SuppressWarnings("removal") - private void run(AccessControlContext accessControlContext) { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - execute(); - return null; - } - }, accessControlContext); - } - private String nextThreadName() { return "JFR Event Stream " + counter.incrementAndGet(); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java index bc9aa7987c3..8560efb9347 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -27,12 +27,10 @@ package jdk.jfr.internal.consumer; import java.io.IOException; import java.nio.file.Path; -import java.security.AccessControlContext; import java.time.Instant; import java.util.Arrays; import java.util.Comparator; import java.util.List; -import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; @@ -44,7 +42,6 @@ import jdk.jfr.internal.LogLevel; import jdk.jfr.internal.LogTag; import jdk.jfr.internal.Logger; import jdk.jfr.internal.PlatformRecording; -import jdk.jfr.internal.SecuritySupport; import jdk.jfr.internal.util.Utils; import jdk.jfr.internal.management.StreamBarrier; @@ -58,7 +55,6 @@ public final class EventDirectoryStream extends AbstractEventStream { private static final Comparator EVENT_COMPARATOR = JdkJfrConsumer.instance().eventComparator(); private final RepositoryFiles repositoryFiles; - private final FileAccess fileAccess; private final PlatformRecording recording; private final StreamBarrier barrier = new StreamBarrier(); private final AtomicLong streamId = new AtomicLong(); @@ -69,20 +65,13 @@ public final class EventDirectoryStream extends AbstractEventStream { private volatile Consumer onCompleteHandler; public EventDirectoryStream( - @SuppressWarnings("removal") - AccessControlContext acc, Path p, - FileAccess fileAccess, PlatformRecording recording, List configurations, boolean allowSubDirectories) throws IOException { - super(acc, configurations); + super(configurations); this.recording = recording; - if (p != null && SecuritySupport.PRIVILEGED == fileAccess) { - throw new SecurityException("Priviliged file access not allowed with potentially malicious Path implementation"); - } - this.fileAccess = Objects.requireNonNull(fileAccess); - this.repositoryFiles = new RepositoryFiles(fileAccess, p, allowSubDirectories); + this.repositoryFiles = new RepositoryFiles(p, allowSubDirectories); this.streamId.incrementAndGet(); Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Stream " + streamId + " started."); } @@ -153,7 +142,7 @@ public final class EventDirectoryStream extends AbstractEventStream { return; } currentChunkStartNanos = repositoryFiles.getTimestamp(path); - try (RecordingInput input = new RecordingInput(path.toFile(), fileAccess)) { + try (RecordingInput input = new RecordingInput(path.toFile())) { input.setStreamed(); currentParser = new ChunkParser(input, disp.parserConfiguration, parserState()); long segmentStart = currentParser.getStartNanos() + currentParser.getChunkDuration(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java index f03e8d8acb4..56d9fe01d79 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -27,7 +27,6 @@ package jdk.jfr.internal.consumer; import java.io.IOException; import java.nio.file.Path; -import java.security.AccessControlContext; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; @@ -45,9 +44,9 @@ public final class EventFileStream extends AbstractEventStream { private ChunkParser currentParser; private RecordedEvent[] cacheSorted; - public EventFileStream(@SuppressWarnings("removal") AccessControlContext acc, Path file) throws IOException { - super(acc, Collections.emptyList()); - this.input = new RecordingInput(file.toFile(), FileAccess.UNPRIVILEGED); + public EventFileStream(Path file) throws IOException { + super(Collections.emptyList()); + this.input = new RecordingInput(file.toFile()); this.input.setStreamed(); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/FileAccess.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/FileAccess.java deleted file mode 100644 index 74a783b0d19..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/FileAccess.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2019, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package jdk.jfr.internal.consumer; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.attribute.FileTime; - -// Protected by modular boundaries. -public abstract class FileAccess { - public static final FileAccess UNPRIVILEGED = new UnPrivileged(); - - public abstract RandomAccessFile openRAF(File f, String mode) throws IOException; - - public abstract DirectoryStream newDirectoryStream(Path repository) throws IOException; - - public abstract String getAbsolutePath(File f) throws IOException; - - public abstract long length(File f) throws IOException; - - public abstract long fileSize(Path p) throws IOException; - - public abstract boolean exists(Path s) throws IOException; - - public abstract boolean isDirectory(Path p); - - public abstract FileTime getLastModified(Path p) throws IOException; - - private static class UnPrivileged extends FileAccess { - @Override - public RandomAccessFile openRAF(File f, String mode) throws IOException { - return new RandomAccessFile(f, mode); - } - - @Override - public DirectoryStream newDirectoryStream(Path dir) throws IOException { - return Files.newDirectoryStream(dir); - } - - @Override - public String getAbsolutePath(File f) throws IOException { - return f.getAbsolutePath(); - } - - @Override - public long length(File f) throws IOException { - return f.length(); - } - - @Override - public long fileSize(Path p) throws IOException { - return Files.size(p); - } - - @Override - public boolean exists(Path p) { - return Files.exists(p); - } - - @Override - public boolean isDirectory(Path p) { - return Files.isDirectory(p); - } - - @Override - public FileTime getLastModified(Path p) throws IOException { - return Files.getLastModifiedTime(p); - } - } -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/OngoingStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/OngoingStream.java index e0dd7fa2ad8..83d8b8c5f17 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/OngoingStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/OngoingStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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 @@ -26,12 +26,12 @@ package jdk.jfr.internal.consumer; import java.io.IOException; import java.nio.ByteBuffer; +import java.nio.file.Files; import java.nio.file.Path; import jdk.jfr.Recording; import jdk.jfr.RecordingState; import jdk.jfr.internal.SecuritySupport; -import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.jfr.internal.management.EventByteStream; import jdk.jfr.internal.management.HiddenWait; import jdk.jfr.internal.management.ManagementSupport; @@ -63,7 +63,7 @@ public final class OngoingStream extends EventByteStream { this.blockSize = blockSize; this.startTimeNanos = startTimeNanos; this.endTimeNanos = endTimeNanos; - this.repositoryFiles = new RepositoryFiles(SecuritySupport.PRIVILEGED, null, false); + this.repositoryFiles = new RepositoryFiles(null, false); } @Override @@ -206,10 +206,10 @@ public final class OngoingStream extends EventByteStream { private boolean ensureInput() throws IOException { if (input == null) { - if (SecuritySupport.getFileSize(new SafePath(path)) < HEADER_SIZE) { + if (Files.size(path) < HEADER_SIZE) { return false; } - input = new RecordingInput(path.toFile(), SecuritySupport.PRIVILEGED); + input = new RecordingInput(path.toFile()); input.setStreamed(); header = new ChunkHeader(input); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java index 69ec73f57fd..33cb928bbbf 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -33,7 +33,6 @@ import java.io.RandomAccessFile; import java.nio.file.Path; import jdk.jfr.internal.management.HiddenWait; -import jdk.jfr.internal.util.Utils; public final class RecordingInput implements DataInput, AutoCloseable { @@ -68,7 +67,6 @@ public final class RecordingInput implements DataInput, AutoCloseable { } } private final int blockSize; - private final FileAccess fileAccess; private final HiddenWait threadSleeper = new HiddenWait(); private long pollCount = 1000; private RandomAccessFile file; @@ -79,26 +77,25 @@ public final class RecordingInput implements DataInput, AutoCloseable { private long size = -1; // Fail fast if setSize(...) has not been called // before parsing - RecordingInput(File f, FileAccess fileAccess, int blockSize) throws IOException { + RecordingInput(File f, int blockSize) throws IOException { this.blockSize = blockSize; - this.fileAccess = fileAccess; initialize(f); } private void initialize(File f) throws IOException { - this.filename = fileAccess.getAbsolutePath(f); - this.file = fileAccess.openRAF(f, "r"); + this.filename = f.getAbsolutePath(); + this.file = new RandomAccessFile(f, "r"); this.position = 0; this.size = -1; this.currentBlock.reset(); previousBlock.reset(); - if (fileAccess.length(f) < 8) { - throw new IOException("Not a valid Flight Recorder file. File length is only " + fileAccess.length(f) + " bytes."); + if (f.length() < 8) { + throw new IOException("Not a valid Flight Recorder file. File length is only " + f.length() + " bytes."); } } - public RecordingInput(File f, FileAccess fileAccess) throws IOException { - this(f, fileAccess, DEFAULT_BLOCK_SIZE); + public RecordingInput(File f) throws IOException { + this(f, DEFAULT_BLOCK_SIZE); } void positionPhysical(long position) throws IOException { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RepositoryFiles.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RepositoryFiles.java index 2cf56c67cb5..09b64efbdd0 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RepositoryFiles.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RepositoryFiles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -28,6 +28,7 @@ package jdk.jfr.internal.consumer; import java.io.IOException; import java.nio.file.DirectoryIteratorException; import java.nio.file.DirectoryStream; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.FileTime; import java.util.ArrayList; @@ -45,7 +46,6 @@ import jdk.jfr.internal.LogLevel; import jdk.jfr.internal.LogTag; import jdk.jfr.internal.Logger; import jdk.jfr.internal.Repository; -import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.jfr.internal.management.HiddenWait;; public final class RepositoryFiles { @@ -57,7 +57,6 @@ public final class RepositoryFiles { } } - private final FileAccess fileAccess; private final NavigableMap pathSet = new TreeMap<>(); private final Map pathLookup = new HashMap<>(); private final HiddenWait waitObject; @@ -65,9 +64,8 @@ public final class RepositoryFiles { private volatile boolean closed; private Path repository; - public RepositoryFiles(FileAccess fileAccess, Path repository, boolean allowSubDirectory) { + public RepositoryFiles(Path repository, boolean allowSubDirectory) { this.repository = repository; - this.fileAccess = fileAccess; this.waitObject = repository == null ? WAIT_OBJECT : new HiddenWait(); this.allowSubDirectory = allowSubDirectory; } @@ -172,14 +170,14 @@ public final class RepositoryFiles { if (repoPath == null) { // Always get the latest repository if 'jcmd JFR.configure // repositorypath=...' has been executed - SafePath sf = Repository.getRepository().getRepositoryPath(); - if (sf == null) { + Path path = Repository.getRepository().getRepositoryPath(); + if (path == null) { return false; // not initialized } - repoPath = sf.toPath(); + repoPath = path; } - try (DirectoryStream dirStream = fileAccess.newDirectoryStream(repoPath)) { + try (DirectoryStream dirStream = Files.newDirectoryStream(repoPath)) { List added = new ArrayList<>(); Set current = new HashSet<>(); for (Path p : dirStream) { @@ -208,7 +206,7 @@ public final class RepositoryFiles { for (Path p : added) { // Only add files that have a complete header // as the JVM may be in progress writing the file - long size = fileAccess.fileSize(p); + long size = Files.size(p); if (size >= ChunkHeader.headerSize()) { long startNanos = readStartTime(p); if (startNanos != -1) { @@ -232,10 +230,10 @@ public final class RepositoryFiles { private Path findSubDirectory(Path repoPath) { FileTime latestTimestamp = null; Path latestPath = null; - try (DirectoryStream dirStream = fileAccess.newDirectoryStream(repoPath)) { + try (DirectoryStream dirStream = Files.newDirectoryStream(repoPath)) { for (Path p : dirStream) { String filename = p.getFileName().toString(); - if (isRepository(filename) && fileAccess.isDirectory(p)) { + if (isRepository(filename) && Files.isDirectory(p)) { FileTime timestamp = getLastModified(p); if (timestamp != null) { if (latestPath == null || latestTimestamp.compareTo(timestamp) <= 0) { @@ -253,7 +251,7 @@ public final class RepositoryFiles { private FileTime getLastModified(Path p) { try { - return fileAccess.getLastModified(p); + return Files.getLastModifiedTime(p); } catch (IOException e) { return null; } @@ -277,7 +275,7 @@ public final class RepositoryFiles { } private long readStartTime(Path p) { - try (RecordingInput in = new RecordingInput(p.toFile(), fileAccess, 100)) { + try (RecordingInput in = new RecordingInput(p.toFile(), 100)) { Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Parsing header for chunk start time"); ChunkHeader c = new ChunkHeader(in); return c.getStartNanos(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/ChunkWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/ChunkWriter.java index d38a5872ade..5e3940e7d11 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/ChunkWriter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/ChunkWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -38,7 +38,6 @@ import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.internal.LongMap; import jdk.jfr.internal.Type; import jdk.jfr.internal.consumer.ChunkHeader; -import jdk.jfr.internal.consumer.FileAccess; import jdk.jfr.internal.Logger; import jdk.jfr.internal.LogLevel; import jdk.jfr.internal.LogTag; @@ -67,7 +66,7 @@ public final class ChunkWriter implements Closeable { public ChunkWriter(Path source, Path destination, Predicate filter) throws IOException { this.destination = destination; this.output = new RecordingOutput(destination.toFile()); - this.input = new RecordingInput(source.toFile(), FileAccess.UNPRIVILEGED); + this.input = new RecordingInput(source.toFile()); this.filter = filter; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java index 516d094b5da..e5b70f40a6c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -43,8 +43,6 @@ import jdk.jfr.internal.JVMSupport; import jdk.jfr.internal.LogLevel; import jdk.jfr.internal.LogTag; import jdk.jfr.internal.Logger; -import jdk.jfr.internal.SecuritySupport; -import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.jfr.internal.util.ValueFormatter; /** @@ -134,7 +132,7 @@ abstract class AbstractDCmd { return JVM.getPid(); } - protected final SafePath resolvePath(Recording recording, String filename) throws InvalidPathException { + protected Path resolvePath(Recording recording, String filename) throws InvalidPathException { if (filename == null) { return makeGenerated(recording, Paths.get(".")); } @@ -142,11 +140,11 @@ abstract class AbstractDCmd { if (Files.isDirectory(path)) { return makeGenerated(recording, path); } - return new SafePath(path.toAbsolutePath().normalize()); + return path.toAbsolutePath().normalize(); } - private SafePath makeGenerated(Recording recording, Path directory) { - return new SafePath(directory.toAbsolutePath().resolve(JVMSupport.makeFilename(recording)).normalize()); + private Path makeGenerated(Recording recording, Path directory) { + return directory.toAbsolutePath().resolve(JVMSupport.makeFilename(recording)).normalize(); } protected final Recording findRecording(String name) throws DCmdException { @@ -158,7 +156,7 @@ abstract class AbstractDCmd { } } - protected final void reportOperationComplete(String actionPrefix, String name, SafePath file) { + protected final void reportOperationComplete(String actionPrefix, String name, Path file) { print(actionPrefix); print(" recording"); if (name != null) { @@ -168,7 +166,7 @@ abstract class AbstractDCmd { print(","); try { print(" "); - long bytes = SecuritySupport.getFileSize(file); + long bytes = Files.size(file); printBytes(bytes); } catch (IOException e) { // Ignore, not essential @@ -219,16 +217,12 @@ abstract class AbstractDCmd { print(ValueFormatter.formatTimespan(timespan, separator)); } - protected final void printPath(SafePath path) { + protected final void printPath(Path path) { if (path == null) { print("N/A"); return; } - try { - printPath(SecuritySupport.getAbsolutePath(path).toPath()); - } catch (IOException ioe) { - printPath(path.toPath()); - } + println(path.toAbsolutePath().toString()); } protected final void printHelpText() { @@ -237,15 +231,6 @@ abstract class AbstractDCmd { } } - protected final void printPath(Path path) { - try { - println(path.toAbsolutePath().toString()); - } catch (SecurityException e) { - // fall back on filename - println(path.toString()); - } - } - private Recording findRecordingById(int id) throws DCmdException { for (Recording r : getFlightRecorder().getRecordings()) { if (r.getId() == id) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java index 8ea49cbd3a5..1d2bad2e9df 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -26,6 +26,7 @@ package jdk.jfr.internal.dcmd; import java.io.IOException; +import java.nio.file.Path; import jdk.jfr.FlightRecorder; import jdk.jfr.internal.LogLevel; @@ -34,7 +35,6 @@ import jdk.jfr.internal.Logger; import jdk.jfr.internal.Options; import jdk.jfr.internal.PrivateAccess; import jdk.jfr.internal.Repository; -import jdk.jfr.internal.SecuritySupport.SafePath; /** * JFR.configure - invoked from native @@ -89,7 +89,7 @@ final class DCmdConfigure extends AbstractDCmd { boolean updated = false; if (repositoryPath != null) { try { - SafePath s = new SafePath(repositoryPath); + Path s = Path.of(repositoryPath); if (FlightRecorder.isInitialized()) { PrivateAccess.getInstance().getPlatformRecorder().migrate(s); } else { @@ -115,7 +115,7 @@ final class DCmdConfigure extends AbstractDCmd { if (dumpPath != null) { try { - Options.setDumpPath(new SafePath(dumpPath)); + Options.setDumpPath(Path.of(dumpPath)); } catch (IOException e) { throw new DCmdException("Could not set " + dumpPath + " to emergency dump path. " + e.getMessage(), e); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java index 7f68ba7ee79..f2397f44ea4 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -40,9 +40,8 @@ import jdk.jfr.Recording; import jdk.jfr.internal.PlatformRecorder; import jdk.jfr.internal.PlatformRecording; import jdk.jfr.internal.PrivateAccess; -import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.jfr.internal.util.ValueParser; -import jdk.jfr.internal.WriteableUserPath; +import jdk.jfr.internal.WriteablePath; /** * JFR.dump @@ -126,17 +125,16 @@ final class DCmdDump extends AbstractDCmd { // If a filename exist, use it // if a filename doesn't exist, use destination set earlier // if destination doesn't exist, generate a filename - WriteableUserPath wup = null; + WriteablePath wp = null; if (recording != null) { PlatformRecording pRecording = PrivateAccess.getInstance().getPlatformRecording(recording); - wup = pRecording.getDestination(); + wp = pRecording.getDestination(); } - if (filename != null || (filename == null && wup == null) ) { - SafePath safe = resolvePath(recording, filename); - wup = new WriteableUserPath(safe.toPath()); + if (filename != null || (filename == null && wp == null) ) { + wp = new WriteablePath(resolvePath(recording, filename)); } - r.dumpStopped(wup); - reportOperationComplete("Dumped", name, new SafePath(wup.getRealPathText())); + r.dumpStopped(wp); + reportOperationComplete("Dumped", name, wp.getReal()); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java index 26c095541b6..634bcd33315 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -29,8 +29,6 @@ import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; -import java.security.AccessControlContext; -import java.security.AccessController; import java.text.ParseException; import java.time.Duration; import java.util.HashSet; @@ -48,8 +46,6 @@ import jdk.jfr.internal.Logger; import jdk.jfr.internal.OldObjectSample; import jdk.jfr.internal.PlatformRecording; import jdk.jfr.internal.PrivateAccess; -import jdk.jfr.internal.SecuritySupport.SafePath; -import jdk.jfr.internal.SecuritySupport; import jdk.jfr.internal.Type; import jdk.jfr.internal.jfc.JFC; import jdk.jfr.internal.jfc.model.JFCModel; @@ -154,7 +150,7 @@ final class DCmdStart extends AbstractDCmd { } recording.setSettings(s); - SafePath safePath = null; + Path dumpPath = null; // Generate dump filename if user has specified a time-bound recording if (duration != null && path == null) { @@ -173,10 +169,10 @@ final class DCmdStart extends AbstractDCmd { // Purposely avoid generating filename in Recording#setDestination due to // security concerns PlatformRecording pr = PrivateAccess.getInstance().getPlatformRecording(recording); - pr.setDumpDirectory(new SafePath(p)); + pr.setDumpDirectory(p); } else { - safePath = resolvePath(recording, path); - recording.setDestination(safePath.toPath()); + dumpPath = resolvePath(recording, path); + recording.setDestination(dumpPath); } } catch (IOException | InvalidPathException e) { recording.close(); @@ -221,10 +217,10 @@ final class DCmdStart extends AbstractDCmd { recording.setMaxSize(250*1024L*1024L); } - if (safePath != null && duration != null) { + if (dumpPath != null && duration != null) { println(" The result will be written to:"); println(); - printPath(safePath); + printPath(dumpPath); } else { println(); println(); @@ -256,7 +252,7 @@ final class DCmdStart extends AbstractDCmd { JFCModel model = new JFCModel(l -> logWarning(l)); for (String setting : settings) { try { - model.parse(JFC.createSafePath(setting)); + model.parse(JFC.ofPath(setting)); } catch (InvalidPathException | IOException | JFCModelException | ParseException e) { throw new DCmdException(JFC.formatException("Could not", e, setting), e); } @@ -463,8 +459,8 @@ final class DCmdStart extends AbstractDCmd { private static String jfcOptions() { try { StringBuilder sb = new StringBuilder(); - for (SafePath s : SecuritySupport.getPredefinedJFCFiles()) { - String name = JFC.nameFromPath(s.toPath()); + for (Path s : JFC.getPredefined()) { + String name = JFC.nameFromPath(s); JFCModel model = JFCModel.create(s, l -> {}); sb.append('\n'); sb.append("Options for ").append(name).append(":\n"); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStop.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStop.java index 5cf983645c6..cda6a03e596 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStop.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStop.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -26,12 +26,12 @@ package jdk.jfr.internal.dcmd; import java.io.IOException; import java.nio.file.InvalidPathException; +import java.nio.file.Path; import java.nio.file.Paths; import jdk.jfr.Recording; import jdk.jfr.internal.PrivateAccess; -import jdk.jfr.internal.SecuritySupport.SafePath; -import jdk.jfr.internal.WriteableUserPath; +import jdk.jfr.internal.WriteablePath; /** * JFR.stop @@ -47,20 +47,20 @@ final class DCmdStop extends AbstractDCmd { String filename = parser.getOption("filename"); try { Recording recording = findRecording(name); - WriteableUserPath path = PrivateAccess.getInstance().getPlatformRecording(recording).getDestination(); - SafePath safePath = path == null ? null : new SafePath(path.getRealPathText()); + WriteablePath wp = PrivateAccess.getInstance().getPlatformRecording(recording).getDestination(); + Path path = wp == null ? null : wp.getReal(); if (filename != null) { try { - // Ensure path is valid. Don't generate safePath if filename == null, as a user may + // Ensure path is valid. Don't generate path if filename == null, as a user may // want to stop recording without a dump - safePath = resolvePath(null, filename); + path = resolvePath(null, filename); recording.setDestination(Paths.get(filename)); } catch (IOException | InvalidPathException e) { throw new DCmdException("Failed to stop %s. Could not set destination for \"%s\" to file %s", recording.getName(), filename, e.getMessage()); } } recording.stop(); - reportOperationComplete("Stopped", recording.getName(), safePath); + reportOperationComplete("Stopped", recording.getName(), path); recording.close(); } catch (InvalidPathException | DCmdException e) { if (filename != null) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/event/EventWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/event/EventWriter.java index 970365ef73d..719fa4e1b4d 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/event/EventWriter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/event/EventWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -27,7 +27,6 @@ package jdk.jfr.internal.event; import jdk.internal.misc.Unsafe; import jdk.jfr.internal.Bits; -import jdk.jfr.internal.EventWriterKey; import jdk.jfr.internal.StringPool; import jdk.jfr.internal.JVM; import jdk.jfr.internal.PlatformEventType; @@ -37,21 +36,8 @@ import jdk.jfr.internal.consumer.StringParser; // would allow it to write arbitrary data into buffers, potentially from // different threads. // -// This is prevented in three ways: -// -// 1. For code to access the jdk.jfr.internal.event package -// at least one event class (for a particular module) must be -// registered having FlightRecorderPermission("registerEvent"). -// -// 2. The EventWriter EventWriterFactory::getEventWriter(long) method can only be linked from -// the UserEvent::commit() method instrumented by JFR. This is ensured by the JVM. -// (The EventWriterFactory class is dynamically generated before the first event -// is instrumented. See EventWriterFactoryRecipe) -// -// 3. Steps 1 and 2 are sufficient to make it fully secure, with or without a Security -// Manager, but as an additional measure, the method EventWriterFactory::getEventWriter(long) -// requires the caller to provide a key that is hard to guess. The key is generated -// into the bytecode of the method invoking getEventWriter(long). +// The EventWriter EventWriterFactory::getEventWriter(long) method can only be linked from +// the UserEvent::commit() method instrumented by JFR. This is ensured by the JVM. // public final class EventWriter { @@ -71,6 +57,14 @@ public final class EventWriter { private PlatformEventType eventType; private boolean largeSize = false; + public static EventWriter getEventWriter() { + EventWriter ew = JVM.getEventWriter(); + if (ew != null) { + return ew; + } + return JVM.newEventWriter(); + } + // User code must not be able to instantiate private EventWriter() { threadID = 0; @@ -239,11 +233,9 @@ public final class EventWriter { } public boolean beginEvent(EventConfiguration configuration, long typeId) { - // Malicious code could take the EventConfiguration object from one - // event class field and assign it to another. This check makes sure - // the event type matches what was added by instrumentation. + // This check makes sure the event type matches what was added by instrumentation. if (configuration.getId() != typeId) { - EventWriterKey.block(); + throw new InternalError("Unexpected type id " + typeId); } if (excluded) { // thread is excluded from writing events diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/JFC.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/JFC.java index 0511ce57001..d89f527ae4b 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/JFC.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/JFC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -46,18 +46,33 @@ import jdk.jfr.internal.jfc.model.JFCModelException; import jdk.jfr.internal.LogLevel; import jdk.jfr.internal.LogTag; import jdk.jfr.internal.Logger; -import jdk.jfr.internal.SecuritySupport; -import jdk.jfr.internal.SecuritySupport.SafePath; +import jdk.jfr.internal.util.Utils; /** * {@link Configuration} factory for JFC files. * */ public final class JFC { + private static final Path JFC_DIRECTORY = Utils.getPathInProperty("java.home", "lib/jfr"); private static final int BUFFER_SIZE = 8192; private static final int MAXIMUM_FILE_SIZE = 1024 * 1024; private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8; private static volatile List knownConfigurations; + public static List getPredefined() { + List list = new ArrayList<>(); + try (var ds = Files.newDirectoryStream(JFC_DIRECTORY)) { + for (Path path : ds) { + String text = path.toString(); + if (text.endsWith(".jfc") && !Files.isDirectory(path)) { + list.add(path); + } + } + } catch (IOException ioe) { + Logger.log(LogTag.JFR, LogLevel.WARN, "Could not access .jfc-files in " + JFC_DIRECTORY + ", " + ioe.getMessage()); + } + return list; + } + /** * Reads a known configuration file (located into a string, but doesn't * parse it until it's being used. @@ -66,14 +81,14 @@ public final class JFC { private final String content; private final String filename; private final String name; - private final SafePath path; + private final Path path; private Configuration configuration; - public KnownConfiguration(SafePath knownPath) throws IOException { + public KnownConfiguration(Path knownPath) throws IOException { this.path = knownPath; this.content = readContent(knownPath); - this.name = nameFromPath(knownPath.toPath()); - this.filename = nullSafeFileName(knownPath.toPath()); + this.name = nameFromPath(knownPath); + this.filename = nullSafeFileName(knownPath); } public boolean isNamed(String name) { @@ -91,12 +106,12 @@ public final class JFC { return name; } - private static String readContent(SafePath knownPath) throws IOException { - if (SecuritySupport.getFileSize(knownPath) > MAXIMUM_FILE_SIZE) { + private static String readContent(Path knownPath) throws IOException { + if (Files.size(knownPath) > MAXIMUM_FILE_SIZE) { throw new IOException("Configuration with more than " + MAXIMUM_FILE_SIZE + " characters can't be read."); } - try (InputStream r = SecuritySupport.newFileInputStream(knownPath)) { + try (InputStream r = Files.newInputStream(knownPath)) { return JFC.readContent(r); } } @@ -114,10 +129,7 @@ public final class JFC { * @throws ParseException if the file can't be parsed * @throws IOException if the file can't be read * - * @throws SecurityException if a security manager exists and its - * {@code checkRead} method denies read access to the file * @see java.io.File#getPath() - * @see java.lang.SecurityManager#checkRead(java.lang.String) */ public static Configuration create(String name, Reader reader) throws IOException, ParseException { try { @@ -136,12 +148,12 @@ public final class JFC { * * @param path textual representation of the path * - * @return a safe path, not null + * @return a path, not null */ - public static SafePath createSafePath(String path) { - for (SafePath predefined : SecuritySupport.getPredefinedJFCFiles()) { + public static Path ofPath(String path) { + for (Path predefined : JFC.getPredefined()) { try { - String name = JFC.nameFromPath(predefined.toPath()); + String name = JFC.nameFromPath(predefined); if (name.equals(path) || (name + ".jfc").equals(path)) { return predefined; } @@ -149,7 +161,7 @@ public final class JFC { throw new InternalError("Error in predefined .jfc file", e); } } - return new SafePath(path); + return Path.of(path); } @@ -172,20 +184,19 @@ public final class JFC { // Invoked by DCmdStart public static Configuration createKnown(String name) throws IOException, ParseException { - // Known name, no need for permission for (KnownConfiguration known : getKnownConfigurations()) { if (known.isNamed(name)) { return known.getConfigurationFile(); } } // Check JFC directory - SafePath path = SecuritySupport.JFC_DIRECTORY; - if (path != null && SecuritySupport.exists(path)) { + Path path = JFC_DIRECTORY; + if (path != null && Files.exists(path)) { for (String extension : Arrays.asList("", JFCParser.FILE_EXTENSION)) { - SafePath file = new SafePath(path.toPath().resolveSibling(name + extension)); - if (SecuritySupport.exists(file) && !SecuritySupport.isDirectory(file)) { - try (Reader r = SecuritySupport.newFileReader(file)) { - String jfcName = nameFromPath(file.toPath()); + Path file = path.resolveSibling(name + extension); + if (Files.exists(file) && !Files.isDirectory(file)) { + try (Reader r = Files.newBufferedReader(file)) { + String jfcName = nameFromPath(file); return JFCParser.createConfiguration(jfcName, r); } } @@ -260,7 +271,7 @@ public final class JFC { private static List getKnownConfigurations() { if (knownConfigurations == null) { List configProxies = new ArrayList<>(); - for (SafePath p : SecuritySupport.getPredefinedJFCFiles()) { + for (Path p : JFC.getPredefined()) { try { configProxies.add(new KnownConfiguration(p)); } catch (IOException ioe) { @@ -281,7 +292,7 @@ public final class JFC { throw new NoSuchFileException("Could not locate configuration with name " + name); } - public static Reader newReader(SafePath sf) throws IOException { + public static Reader newReader(Path sf) throws IOException { for (KnownConfiguration c : getKnownConfigurations()) { if (c.path.equals(sf)) { return new StringReader(c.content); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/JFCModel.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/JFCModel.java index e9b4208c148..e0b5fb4a6f3 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/JFCModel.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/JFCModel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, 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 @@ -27,6 +27,7 @@ package jdk.jfr.internal.jfc.model; import java.io.IOException; import java.io.PrintWriter; import java.io.Reader; +import java.nio.file.Path; import java.text.ParseException; import java.util.ArrayList; import java.util.Collections; @@ -35,7 +36,6 @@ import java.util.List; import java.util.Map; import java.util.function.Consumer; -import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.jfr.internal.jfc.JFC; import static java.nio.charset.StandardCharsets.UTF_8; @@ -65,7 +65,7 @@ public final class JFCModel { this.logger = logger; } - public void parse(SafePath file) throws IOException, JFCModelException, ParseException { + public void parse(Path file) throws IOException, JFCModelException, ParseException { JFCModel model = JFCModel.create(file, logger); for (var entry : model.controls.entrySet()) { String name = entry.getKey(); @@ -80,7 +80,7 @@ public final class JFCModel { } } - public static JFCModel create(SafePath file, Consumer logger) throws IOException, JFCModelException, ParseException{ + public static JFCModel create(Path file, Consumer logger) throws IOException, JFCModelException, ParseException{ if (file.toString().equals("none")) { XmlConfiguration configuration = new XmlConfiguration(); configuration.setAttribute("version", "2.0"); @@ -154,7 +154,7 @@ public final class JFCModel { return result; } - public void saveToFile(SafePath path) throws IOException { + public void saveToFile(Path path) throws IOException { try (PrintWriter p = new PrintWriter(path.toFile(), UTF_8)) { PrettyPrinter pp = new PrettyPrinter(p); pp.print(configuration); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ChunkFilename.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ChunkFilename.java index 66cd982bb51..0d8290b206e 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ChunkFilename.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ChunkFilename.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, 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 @@ -25,13 +25,12 @@ package jdk.jfr.internal.management; import java.nio.file.Paths; +import java.nio.file.Files; import java.nio.file.Path; import java.time.LocalDateTime; import java.io.IOException; -import jdk.jfr.internal.SecuritySupport; import jdk.jfr.internal.util.ValueFormatter; -import jdk.jfr.internal.consumer.FileAccess; // Allows a remote streaming client to create chunk files // with same naming scheme as the JVM. @@ -40,23 +39,12 @@ public final class ChunkFilename { private static final String FILE_EXTENSION = ".jfr"; private final Path directory; - private final FileAccess fileAcess; private Path lastPath; private int counter; - public static ChunkFilename newUnpriviliged(Path directory) { - return new ChunkFilename(directory, FileAccess.UNPRIVILEGED); - } - - public static ChunkFilename newPriviliged(Path directory) { - return new ChunkFilename(directory, SecuritySupport.PRIVILEGED); - } - - private ChunkFilename(Path directory, FileAccess fileAccess) { - // Avoid malicious implementations of Path interface - this.directory = Paths.get(directory.toString()); - this.fileAcess = fileAccess; + public ChunkFilename(Path directory) { + this.directory = directory; } public String next(LocalDateTime time) throws IOException { @@ -65,7 +53,7 @@ public final class ChunkFilename { // If less than one file per second (typically case) if (lastPath == null || !p.equals(lastPath)) { - if (!fileAcess.exists(p)) { + if (!Files.exists(p)) { counter = 1; // reset counter lastPath = p; return p.toString(); @@ -77,7 +65,7 @@ public final class ChunkFilename { String extendedName = makeExtendedName(filename, counter); p = directory.resolve(extendedName); counter++; - if (!fileAcess.exists(p)) { + if (!Files.exists(p)) { return p.toString(); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java index 165419cc34a..1f5963d0277 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -34,8 +34,6 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.function.Consumer; -import java.security.AccessControlContext; - import jdk.jfr.Configuration; import jdk.jfr.EventSettings; import jdk.jfr.EventType; @@ -49,15 +47,12 @@ import jdk.jfr.internal.Logger; import jdk.jfr.internal.MetadataRepository; import jdk.jfr.internal.PlatformRecording; import jdk.jfr.internal.PrivateAccess; -import jdk.jfr.internal.SecuritySupport; -import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.jfr.internal.util.Utils; import jdk.jfr.internal.util.ValueFormatter; import jdk.jfr.internal.util.ValueParser; -import jdk.jfr.internal.WriteableUserPath; +import jdk.jfr.internal.WriteablePath; import jdk.jfr.internal.consumer.AbstractEventStream; import jdk.jfr.internal.consumer.EventDirectoryStream; -import jdk.jfr.internal.consumer.FileAccess; /** * The management API in module jdk.management.jfr should be built on top of the @@ -84,7 +79,6 @@ public final class ManagementSupport { // public static List getEventTypes() { // would normally be checked when a Flight Recorder instance is created - SecuritySupport.checkAccessFlightRecorder(); if (JVMSupport.isNotAvailable()) { return List.of(); } @@ -121,17 +115,16 @@ public final class ManagementSupport { // requires access to jdk.jfr.internal.PlatformRecording public static String getDestinationOriginalText(Recording recording) { PlatformRecording pr = PrivateAccess.getInstance().getPlatformRecording(recording); - WriteableUserPath wup = pr.getDestination(); - return wup == null ? null : wup.getOriginalText(); + WriteablePath wp = pr.getDestination(); + return wp == null ? null : wp.getPath().toString(); } // Needed to check if destination can be set, so FlightRecorderMXBean::setRecordingOption // can abort if not all data is valid - public static void checkSetDestination(Recording recording, String destination) throws IOException{ + public static void checkSetDestination(Recording recording, String destination) throws IOException { PlatformRecording pr = PrivateAccess.getInstance().getPlatformRecording(recording); if(destination != null){ - WriteableUserPath wup = new WriteableUserPath(Paths.get(destination)); - pr.checkSetDestination(wup); + pr.checkSetDestination(new WriteablePath(Paths.get(destination))); } } @@ -143,7 +136,7 @@ public final class ManagementSupport { // Needed callback to detect when a chunk has been parsed. public static void removePath(Recording recording, Path path) { PlatformRecording pr = PrivateAccess.getInstance().getPlatformRecording(recording); - pr.removePath(new SafePath(path)); + pr.removePath(path); } // Needed callback to detect when a chunk has been parsed. @@ -169,14 +162,10 @@ public final class ManagementSupport { // EventStream::onMetadataData need to supply MetadataEvent // with configuration objects public static EventStream newEventDirectoryStream( - @SuppressWarnings("removal") - AccessControlContext acc, Path directory, List confs) throws IOException { return new EventDirectoryStream( - acc, directory, - FileAccess.UNPRIVILEGED, null, confs, false diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/JavaEventTask.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/JavaEventTask.java index 18729685a6d..55113f7d3f4 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/JavaEventTask.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/JavaEventTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, 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 @@ -30,9 +30,9 @@ import jdk.jfr.internal.MetadataRepository; import jdk.jfr.internal.PlatformEventType; import jdk.jfr.internal.PrivateAccess; /** - * Base class for periodic Java events. + * Class for periodic Java events. */ -abstract class JavaEventTask extends EventTask { +final class JavaEventTask extends EventTask { private final Runnable runnable; public JavaEventTask(Class eventClass, Runnable runnable) { @@ -48,7 +48,8 @@ abstract class JavaEventTask extends EventTask { return PrivateAccess.getInstance().getPlatformEventType(eventType); } - protected final Runnable getRunnable() { - return runnable; + @Override + public void execute(long timestamp, PeriodicType periodicType) { + runnable.run(); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/LookupKey.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/LookupKey.java index 5bbfbef70ae..bc4006aaff6 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/LookupKey.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/LookupKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, 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 @@ -25,11 +25,8 @@ package jdk.jfr.internal.periodic; /** - * Lookup key that can safely be used in a {@code Map}. - *

- * {@code Runnable} objects can't be used with {@code LinkedHashMap} as it - * invokes {@code hashCode} and {@code equals}, for example when resizing the - * {@code Map}, possibly in a non-secure context. + * Lookup key that can be used in a {@code Map} in + * case hashCode and equals are incorrectly overridden. *

* {@code IdentityHashMap} can't be used as it will not preserve order. */ diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicEvents.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicEvents.java index a68af8ad25b..8cbf6334e64 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicEvents.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicEvents.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -24,7 +24,6 @@ */ package jdk.jfr.internal.periodic; -import java.security.AccessControlContext; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicLong; @@ -58,18 +57,14 @@ public final class PeriodicEvents { // State only to be read and modified by periodic task thread private static long lastTimeMillis; - public static void addJDKEvent(Class eventClass, Runnable runnable) { - taskRepository.add(new JDKEventTask(eventClass, runnable)); + public static void addJavaEvent(Class eventClass, Runnable runnable) { + taskRepository.add(new JavaEventTask(eventClass, runnable)); } public static void addJVMEvent(PlatformEventType eventType) { taskRepository.add(new JVMEventTask(eventType)); } - public static void addUserEvent(@SuppressWarnings("removal") AccessControlContext acc, Class eventClass, Runnable runnable) { - taskRepository.add(new UserEventTask(acc, eventClass, runnable)); - } - public static boolean removeEvent(Runnable runnable) { return taskRepository.removeTask(runnable); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicTask.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicTask.java index 876b9ecbc92..b180d507481 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicTask.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/PeriodicTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, 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 @@ -40,9 +40,6 @@ import jdk.jfr.internal.Logger; * / \ * / \ * JVMEventTask JavaEventTask - * / \ - * / \ - * UserEventTask JDKEventTask * *

* State modifications should only be done from the periodic task thread. @@ -127,8 +124,8 @@ abstract class PeriodicTask { try { execute(timestamp, periodicType); } catch (Throwable e) { - // Prevent malicious user to propagate exception callback in the wrong context - Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, "Exception occurred during execution of " + name); + String msg = "Exception occurred during execution of " + name + ". " + e.getMessage(); + Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, msg); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/UserEventTask.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/UserEventTask.java deleted file mode 100644 index 1241cd7fb0b..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/UserEventTask.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2023, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ -package jdk.jfr.internal.periodic; - -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Objects; - -import jdk.internal.event.Event; -import jdk.jfr.internal.LogLevel; -import jdk.jfr.internal.LogTag; -import jdk.jfr.internal.Logger; - -/** - * Class to be used with user-defined events that runs untrusted code. - *

- * This class can be removed once the Security Manager is no longer supported. - */ -final class UserEventTask extends JavaEventTask { - @SuppressWarnings("removal") - private final AccessControlContext controlContext; - - public UserEventTask(@SuppressWarnings("removal") AccessControlContext controlContext, Class eventClass, Runnable runnable) { - super(eventClass, runnable); - this.controlContext = Objects.requireNonNull(controlContext); - } - - @SuppressWarnings("removal") - @Override - public void execute(long timestamp, PeriodicType periodicType) { - AccessController.doPrivileged((PrivilegedAction) () -> { - execute(); - return null; - }, controlContext); - } - - private void execute() { - try { - getRunnable().run(); - if (Logger.shouldLog(LogTag.JFR_EVENT, LogLevel.DEBUG)) { - Logger.log(LogTag.JFR_EVENT, LogLevel.DEBUG, "Executed periodic task for " + getEventType().getLogName()); - } - } catch (Throwable t) { - // Prevent malicious user to propagate exception callback in the wrong context - Logger.log(LogTag.JFR_EVENT, LogLevel.WARN, "Exception occurred during execution of period task for " + getEventType().getLogName()); - } - } -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/BooleanSetting.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/BooleanSetting.java index 72ffcac72c9..f5cc1495738 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/BooleanSetting.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/BooleanSetting.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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 @@ -28,9 +28,10 @@ package jdk.jfr.internal.settings; import java.util.Objects; import java.util.Set; +import jdk.jfr.SettingControl; import jdk.jfr.internal.PlatformEventType; -abstract class BooleanSetting extends JDKSettingControl { +abstract class BooleanSetting extends SettingControl { private final PlatformEventType eventType; private final String defaultValue; private String value; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/CutoffSetting.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/CutoffSetting.java index 68950d71b63..2f7d9f8e872 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/CutoffSetting.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/CutoffSetting.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, 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 @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.Set; import jdk.jfr.Description; +import jdk.jfr.SettingControl; import jdk.jfr.Label; import jdk.jfr.MetadataDefinition; import jdk.jfr.Name; @@ -44,7 +45,7 @@ import jdk.jfr.internal.util.ValueParser; @Description("Limit running time of event") @Name(Type.SETTINGS_PREFIX + "Cutoff") @Timespan -public final class CutoffSetting extends JDKSettingControl { +public final class CutoffSetting extends SettingControl { public static final String DEFAULT_VALUE = ValueParser.INFINITY; private String value = DEFAULT_VALUE; private final PlatformEventType eventType; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/JDKSettingControl.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/JDKSettingControl.java deleted file mode 100644 index 46f224bada6..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/JDKSettingControl.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2020, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package jdk.jfr.internal.settings; - -import jdk.jfr.SettingControl; - -/** - * SettingControls that derive from this class avoids executing settings - * modifications in a AccessController.doPrivilege(...) block. - */ -public abstract class JDKSettingControl extends SettingControl { -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/LevelSetting.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/LevelSetting.java index 9531f75c925..750e20d9cdd 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/LevelSetting.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/LevelSetting.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, 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 @@ -33,13 +33,14 @@ import java.util.Set; import jdk.jfr.Label; import jdk.jfr.MetadataDefinition; import jdk.jfr.Name; +import jdk.jfr.SettingControl; import jdk.jfr.internal.PlatformEventType; import jdk.jfr.internal.Type; @MetadataDefinition @Label("Level") @Name(Type.SETTINGS_PREFIX + "Level") -public final class LevelSetting extends JDKSettingControl { +public final class LevelSetting extends SettingControl { private final PlatformEventType eventType; private final List levels; private String value; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/PeriodSetting.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/PeriodSetting.java index 22fef2691aa..902584a8819 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/PeriodSetting.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/PeriodSetting.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -32,6 +32,7 @@ import jdk.jfr.Description; import jdk.jfr.Label; import jdk.jfr.MetadataDefinition; import jdk.jfr.Name; +import jdk.jfr.SettingControl; import jdk.jfr.internal.PlatformEventType; import jdk.jfr.internal.Type; import jdk.jfr.internal.util.ValueParser; @@ -41,7 +42,7 @@ import static jdk.jfr.internal.util.ValueParser.MISSING; @Label("Period") @Description("Record event at interval") @Name(Type.SETTINGS_PREFIX + "Period") -public final class PeriodSetting extends JDKSettingControl { +public final class PeriodSetting extends SettingControl { private static final long typeId = Type.getTypeId(PeriodSetting.class); public static final String EVERY_CHUNK = "everyChunk"; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/ThresholdSetting.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/ThresholdSetting.java index 8870417f9dd..83a55726707 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/ThresholdSetting.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/ThresholdSetting.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -34,6 +34,7 @@ import jdk.jfr.Description; import jdk.jfr.Label; import jdk.jfr.MetadataDefinition; import jdk.jfr.Name; +import jdk.jfr.SettingControl; import jdk.jfr.Timespan; import jdk.jfr.internal.PlatformEventType; import jdk.jfr.internal.Type; @@ -44,7 +45,7 @@ import jdk.jfr.internal.util.ValueParser; @Name(Type.SETTINGS_PREFIX + "Threshold") @Description("Record event with duration above or equal to threshold") @Timespan -public final class ThresholdSetting extends JDKSettingControl { +public final class ThresholdSetting extends SettingControl { public static final String DEFAULT_VALUE = "0 ns"; private static final long typeId = Type.getTypeId(ThresholdSetting.class); private String value = DEFAULT_VALUE; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/ThrottleSetting.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/ThrottleSetting.java index c18031d514f..0527d7e8689 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/ThrottleSetting.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/ThrottleSetting.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Datadog, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -36,6 +36,7 @@ import jdk.jfr.Description; import jdk.jfr.Label; import jdk.jfr.MetadataDefinition; import jdk.jfr.Name; +import jdk.jfr.SettingControl; import jdk.jfr.internal.PlatformEventType; import jdk.jfr.internal.Throttle; import jdk.jfr.internal.Type; @@ -47,7 +48,7 @@ import jdk.jfr.internal.util.Utils; @Label("Throttle") @Description("Throttles the emission rate for an event") @Name(Type.SETTINGS_PREFIX + "Throttle") -public final class ThrottleSetting extends JDKSettingControl { +public final class ThrottleSetting extends SettingControl { public static final String DEFAULT_VALUE = Throttle.DEFAULT; private final PlatformEventType eventType; private String value = DEFAULT_VALUE; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java index 974e8846aa4..d76f182a8a8 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -52,7 +52,7 @@ abstract class Command { List commands = new ArrayList<>(); commands.add(new Print()); // Uncomment when developing new queries for the view command - // commands.add(new Query()); + commands.add(new Query()); commands.add(new View()); commands.add(new Configure()); commands.add(new Metadata()); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Configure.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Configure.java index 63b2d8fe74f..048763c4cc1 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Configure.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Configure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, 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 @@ -38,7 +38,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.jfr.internal.jfc.JFC; import jdk.jfr.internal.jfc.model.AbortException; import jdk.jfr.internal.jfc.model.JFCModel; @@ -129,7 +128,7 @@ final class Configure extends Command { stream.println("Options for " + name + ":"); stream.println(); try { - SafePath path = JFC.createSafePath(name); + Path path = JFC.ofPath(name); JFCModel parameters = JFCModel.create(path, l -> stream.println("Warning! " + l)); for (XmlInput input : parameters.getInputs()) { stream.println(" " + input.getOptionSyntax()); @@ -144,7 +143,7 @@ final class Configure extends Command { public void execute(Deque options) throws UserSyntaxException, UserDataException { boolean interactive = false; boolean log = false; - SafePath output = null; + Path output = null; Map keyValues = new LinkedHashMap<>(); int optionCount = options.size(); while (optionCount > 0) { @@ -192,7 +191,7 @@ final class Configure extends Command { return false; } - private void configure(boolean interactive, boolean log, SafePath output, Map options) throws UserDataException { + private void configure(boolean interactive, boolean log, Path output, Map options) throws UserDataException { UserInterface ui = new UserInterface(); if (log) { SettingsLog.enable(); @@ -201,14 +200,14 @@ final class Configure extends Command { model.setLabel("Custom"); for (String input : inputFiles) { try { - model.parse(JFC.createSafePath(input)); + model.parse(JFC.ofPath(input)); } catch (InvalidPathException | IOException | JFCModelException | ParseException e) { throw new UserDataException(JFC.formatException("could not", e, input)); } } try { if (output == null) { - output = new SafePath(Path.of("custom.jfc")); + output = Path.of("custom.jfc"); } for (var option : options.entrySet()) { model.configure(option.getKey(), option.getValue()); @@ -230,7 +229,7 @@ final class Configure extends Command { } model.saveToFile(output); ui.println("Configuration written successfully to:"); - ui.println(output.toPath().toAbsolutePath().toString()); + ui.println(output.toAbsolutePath().toString()); } catch (IllegalArgumentException iae) { throw new UserDataException(iae.getMessage()); } catch (FileNotFoundException ffe) { @@ -246,7 +245,7 @@ final class Configure extends Command { } } - private static SafePath filename(UserInterface ui, SafePath file) throws AbortException { + private static Path filename(UserInterface ui, Path file) throws AbortException { ui.println(); ui.println("Filename: " + file + " (default)"); while (true) { @@ -256,7 +255,7 @@ final class Configure extends Command { return file; } if (line.endsWith(".jfc")) { - return new SafePath(line); + return Path.of(line); } ui.println("Filename must end with .jfc."); } catch (InvalidPathException ipe) { @@ -265,14 +264,14 @@ final class Configure extends Command { } } - private SafePath makeJFCPath(String file) throws UserDataException, UserSyntaxException { + private Path makeJFCPath(String file) throws UserDataException, UserSyntaxException { if (file.startsWith("--")) { throw new UserSyntaxException("missing file"); } try { Path path = Path.of(file).toAbsolutePath(); ensureFileExtension(path, ".jfc"); - return new SafePath(path); + return path; } catch (IOError ioe) { throw new UserDataException("i/o error reading file '" + file + "', " + ioe.getMessage()); } catch (InvalidPathException ipe) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Disassemble.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Disassemble.java index 48dd5247568..25211f84bd4 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Disassemble.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Disassemble.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -41,7 +41,6 @@ import java.util.Deque; import java.util.List; import jdk.jfr.internal.consumer.ChunkHeader; -import jdk.jfr.internal.consumer.FileAccess; import jdk.jfr.internal.consumer.RecordingInput; import jdk.jfr.internal.util.UserDataException; import jdk.jfr.internal.util.UserSyntaxException; @@ -166,7 +165,7 @@ final class Disassemble extends Command { } private List findChunkSizes(Path p) throws IOException { - try (RecordingInput input = new RecordingInput(p.toFile(), FileAccess.UNPRIVILEGED)) { + try (RecordingInput input = new RecordingInput(p.toFile())) { List sizes = new ArrayList<>(); ChunkHeader ch = new ChunkHeader(input); sizes.add(ch.getSize()); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java index 12a468b2e89..08ab475fa68 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -41,7 +41,6 @@ import jdk.jfr.EventType; import jdk.jfr.internal.MetadataDescriptor; import jdk.jfr.internal.Type; import jdk.jfr.internal.consumer.ChunkHeader; -import jdk.jfr.internal.consumer.FileAccess; import jdk.jfr.internal.consumer.RecordingInput; import jdk.jfr.internal.util.UserDataException; import jdk.jfr.internal.util.UserSyntaxException; @@ -93,7 +92,7 @@ final class Summary extends Command { long totalDuration = 0; long chunks = 0; - try (RecordingInput input = new RecordingInput(p.toFile(), FileAccess.UNPRIVILEGED)) { + try (RecordingInput input = new RecordingInput(p.toFile())) { ChunkHeader first = new ChunkHeader(input); ChunkHeader ch = first; String eventPrefix = Type.EVENT_NAME_PREFIX; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventWriterFactoryRecipe.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/util/DirectoryCleaner.java similarity index 56% rename from src/jdk.jfr/share/classes/jdk/jfr/internal/EventWriterFactoryRecipe.java rename to src/jdk.jfr/share/classes/jdk/jfr/internal/util/DirectoryCleaner.java index de59ea92d69..2067a8ebec1 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventWriterFactoryRecipe.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/util/DirectoryCleaner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 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 @@ -22,23 +22,33 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.jfr.internal; +package jdk.jfr.internal.util; -import jdk.jfr.internal.event.EventWriter; +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; -// This class is not directly used but renamed to -// jdk.jfr.internal.event.EventWriterFactory and loaded dynamically -// when the first event class is bytecode instrumented. -// See JVMUpcalls and EventWriterKey::ensureEventWriterFactory() -public final class EventWriterFactoryRecipe { - private static final long KEY = EventWriterKey.getKey(); +public final class DirectoryCleaner extends SimpleFileVisitor { - public static EventWriter getEventWriter(long key) { - if (key == KEY) { - EventWriter ew = JVM.getEventWriter(); - return ew != null ? ew : JVM.newEventWriter(); + public static void clear(Path path) throws IOException { + Files.walkFileTree(path, new DirectoryCleaner()); + } + + @Override + public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException { + Files.delete(path); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + if (exc != null) { + throw exc; } - EventWriterKey.block(); - return null; // Can't reach here. + Files.delete(dir); + return FileVisitResult.CONTINUE; } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/util/Utils.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/util/Utils.java index c15e87709c5..777725f88d4 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/util/Utils.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/util/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -25,7 +25,9 @@ package jdk.jfr.internal.util; +import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.io.RandomAccessFile; import java.lang.annotation.Annotation; import java.lang.annotation.Repeatable; @@ -448,4 +450,13 @@ public final class Utils { } return null; } + + public static Path getPathInProperty(String prop, String subPath) { + String path = System.getProperty(prop); + if (path == null) { + return null; + } + File file = subPath == null ? new File(path) : new File(path, subPath); + return file.toPath().toAbsolutePath(); + } } diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java index 24fd768dd41..1ed2a2a05ae 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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 @@ -151,7 +151,7 @@ final class DiskRepository implements Closeable { public DiskRepository(Path path, boolean deleteDirectory) throws IOException { this.directory = path; this.deleteDirectory = deleteDirectory; - this.chunkFilename = ChunkFilename.newUnpriviliged(path); + this.chunkFilename = new ChunkFilename(path); } public synchronized void write(byte[] bytes) throws IOException { diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java index e65b114d7aa..bb2470d5a0b 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -30,9 +30,6 @@ import java.io.InputStream; import java.io.StringReader; import java.nio.file.Path; import java.nio.file.Paths; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.text.ParseException; import java.time.Instant; import java.util.ArrayList; @@ -67,7 +64,6 @@ import jdk.jfr.Configuration; import jdk.jfr.EventType; import jdk.jfr.FlightRecorder; import jdk.jfr.FlightRecorderListener; -import jdk.jfr.FlightRecorderPermission; import jdk.jfr.Recording; import jdk.jfr.RecordingState; import jdk.jfr.internal.management.ManagementSupport; @@ -80,12 +76,9 @@ final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements Fli private final NotificationListener listener; private final NotificationFilter filter; private final Object handback; - @SuppressWarnings("removal") - private final AccessControlContext context; @SuppressWarnings("removal") public MXBeanListener(NotificationListener listener, NotificationFilter filter, Object handback) { - this.context = AccessController.getContext(); this.listener = listener; this.filter = filter; this.handback = handback; @@ -93,13 +86,7 @@ final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements Fli @SuppressWarnings("removal") public void recordingStateChanged(Recording recording) { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - sendNotification(createNotification(recording)); - return null; - } - }, context); + sendNotification(createNotification(recording)); } } @@ -124,25 +111,21 @@ final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements Fli @Override public void startRecording(long id) { - MBeanUtils.checkControl(); getExistingRecording(id).start(); } @Override public boolean stopRecording(long id) { - MBeanUtils.checkControl(); return getExistingRecording(id).stop(); } @Override public void closeRecording(long id) { - MBeanUtils.checkControl(); getExistingRecording(id).close(); } @Override public long openStream(long id, Map options) throws IOException { - MBeanUtils.checkControl(); if (!FlightRecorder.isInitialized()) { throw new IllegalArgumentException("No recording available with id " + id); } @@ -169,19 +152,16 @@ final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements Fli @Override public void closeStream(long streamIdentifier) throws IOException { - MBeanUtils.checkControl(); streamHandler.getStream(streamIdentifier).close(); } @Override public byte[] readStream(long streamIdentifier) throws IOException { - MBeanUtils.checkMonitor(); return streamHandler.getStream(streamIdentifier).read(); } @Override public List getRecordings() { - MBeanUtils.checkMonitor(); if (!FlightRecorder.isInitialized()) { return Collections.emptyList(); } @@ -190,60 +170,39 @@ final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements Fli @Override public List getConfigurations() { - MBeanUtils.checkMonitor(); return MBeanUtils.transformList(Configuration.getConfigurations(), ConfigurationInfo::new); } @Override public List getEventTypes() { - MBeanUtils.checkMonitor(); - @SuppressWarnings("removal") - List eventTypes = AccessController.doPrivileged(new PrivilegedAction>() { - @Override - public List run() { - return ManagementSupport.getEventTypes(); - } - }, null, new FlightRecorderPermission("accessFlightRecorder")); - - return MBeanUtils.transformList(eventTypes, EventTypeInfo::new); + return MBeanUtils.transformList(ManagementSupport.getEventTypes(), EventTypeInfo::new); } @Override public Map getRecordingSettings(long recording) throws IllegalArgumentException { - MBeanUtils.checkMonitor(); return getExistingRecording(recording).getSettings(); } @Override public void setRecordingSettings(long recording, Map settings) throws IllegalArgumentException { Objects.requireNonNull(settings, "settings"); - MBeanUtils.checkControl(); getExistingRecording(recording).setSettings(settings); } - @SuppressWarnings("removal") @Override public long newRecording() { - MBeanUtils.checkControl(); getRecorder(); // ensure notification listener is setup - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Recording run() { - return new Recording(); - } - }, null, new FlightRecorderPermission("accessFlightRecorder")).getId(); + return new Recording().getId(); } @Override public long takeSnapshot() { - MBeanUtils.checkControl(); return getRecorder().takeSnapshot().getId(); } @Override public void setConfiguration(long recording, String contents) throws IllegalArgumentException { Objects.requireNonNull(contents, "contents"); - MBeanUtils.checkControl(); try { Configuration c = Configuration.create(new StringReader(contents)); getExistingRecording(recording).setSettings(c.getSettings()); @@ -255,7 +214,6 @@ final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements Fli @Override public void setPredefinedConfiguration(long recording, String configurationName) throws IllegalArgumentException { Objects.requireNonNull(configurationName, "configurationName"); - MBeanUtils.checkControl(); Recording r = getExistingRecording(recording); for (Configuration c : Configuration.getConfigurations()) { if (c.getName().equals(configurationName)) { @@ -269,14 +227,12 @@ final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements Fli @Override public void copyTo(long recording, String outputFile) throws IOException { Objects.requireNonNull(outputFile, "outputFile"); - MBeanUtils.checkControl(); getExistingRecording(recording).dump(Paths.get(outputFile)); } @Override public void setRecordingOptions(long recording, Map options) throws IllegalArgumentException { Objects.requireNonNull(options, "options"); - MBeanUtils.checkControl(); // Make local copy to prevent concurrent modification Map ops = new HashMap(options); for (Map.Entry entry : ops.entrySet()) { @@ -315,7 +271,6 @@ final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements Fli @Override public Map getRecordingOptions(long recording) throws IllegalArgumentException { - MBeanUtils.checkMonitor(); Recording r = getExistingRecording(recording); Map options = HashMap.newHashMap(10); options.put(OPTION_DUMP_ON_EXIT, String.valueOf(r.getDumpOnExit())); @@ -330,8 +285,7 @@ final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements Fli } @Override - public long cloneRecording(long id, boolean stop) throws IllegalStateException, SecurityException { - MBeanUtils.checkControl(); + public long cloneRecording(long id, boolean stop) throws IllegalStateException { return getRecording(id).copy(stop).getId(); } @@ -397,16 +351,11 @@ final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements Fli } @SuppressWarnings("removal") - private FlightRecorder getRecorder() throws SecurityException { + private FlightRecorder getRecorder() { // Synchronize on some private object that is always available synchronized (streamHandler) { if (recorder == null) { - recorder = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public FlightRecorder run() { - return FlightRecorder.getFlightRecorder(); - } - }, null, new FlightRecorderPermission("accessFlightRecorder")); + recorder = FlightRecorder.getFlightRecorder(); } return recorder; } @@ -425,13 +374,7 @@ final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements Fli public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) { MXBeanListener mxbeanListener = new MXBeanListener(listener, filter, handback); listeners.add(mxbeanListener); - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run(){ - FlightRecorder.addListener(mxbeanListener); - return null; - } - }, null, new FlightRecorderPermission("accessFlightRecorder")); + FlightRecorder.addListener(mxbeanListener); super.addNotificationListener(listener, filter, handback); } diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/MBeanUtils.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/MBeanUtils.java index 05d2166329f..cf05f840cbe 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/MBeanUtils.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/MBeanUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -25,8 +25,6 @@ package jdk.management.jfr; import java.io.IOException; -import java.lang.management.ManagementPermission; -import java.security.Permission; import java.time.DateTimeException; import java.time.Duration; import java.time.Instant; @@ -43,9 +41,6 @@ import jdk.jfr.internal.management.ManagementSupport; final class MBeanUtils { - private static final Permission monitor = new ManagementPermission("monitor"); - private static final Permission control = new ManagementPermission("control"); - static ObjectName createObjectName() { try { return new ObjectName(FlightRecorderMXBean.MXBEAN_NAME); @@ -54,22 +49,6 @@ final class MBeanUtils { } } - static void checkControl() { - @SuppressWarnings("removal") - SecurityManager secManager = System.getSecurityManager(); - if (secManager != null) { - secManager.checkPermission(control); - } - } - - static void checkMonitor() { - @SuppressWarnings("removal") - SecurityManager secManager = System.getSecurityManager(); - if (secManager != null) { - secManager.checkPermission(monitor); - } - } - static List transformList(List source, Function function) { return source.stream().map(function).collect(Collectors.toList()); } diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java index e6dc9700c00..662fe891244 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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 @@ -32,8 +32,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; -import java.security.AccessControlContext; -import java.security.AccessController; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; @@ -44,7 +42,6 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.Future; import java.util.function.Consumer; -import java.security.AccessControlException; import javax.management.JMX; import javax.management.MBeanServerConnection; import javax.management.ObjectName; @@ -149,8 +146,6 @@ public final class RemoteRecordingStream implements EventStream { final FlightRecorderMXBean mbean; final long recordingId; final EventStream stream; - @SuppressWarnings("removal") - final AccessControlContext accessControllerContext; final DiskRepository repository; final Instant creationTime; final Object lock = new Object(); @@ -205,9 +200,7 @@ public final class RemoteRecordingStream implements EventStream { private RemoteRecordingStream(MBeanServerConnection connection, Path directory, boolean delete) throws IOException { Objects.requireNonNull(connection, "connection"); Objects.requireNonNull(directory, "directory"); - accessControllerContext = AccessController.getContext(); - // Make sure users can't implement malicious version of a Path object. - path = Paths.get(directory.toString()); + path = directory; if (!Files.exists(path)) { throw new IOException("Download directory doesn't exist"); } @@ -219,7 +212,7 @@ public final class RemoteRecordingStream implements EventStream { creationTime = Instant.now(); mbean = createProxy(connection); recordingId = createRecording(); - stream = ManagementSupport.newEventDirectoryStream(accessControllerContext, path, configurations(mbean)); + stream = ManagementSupport.newEventDirectoryStream(path, configurations(mbean)); stream.setStartTime(Instant.MIN); repository = new DiskRepository(path, delete); ManagementSupport.setOnChunkCompleteHandler(stream, new ChunkConsumer(repository)); diff --git a/test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java b/test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java index 2780f396f05..29e666a830c 100644 --- a/test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java +++ b/test/jdk/jdk/jfr/jcmd/TestJcmdConfigure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, 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 @@ -25,12 +25,12 @@ package jdk.jfr.jcmd; import java.io.File; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import jdk.jfr.internal.Repository; -import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.jfr.internal.Options; import jdk.test.lib.Asserts; import jdk.test.lib.Utils; @@ -131,17 +131,17 @@ public class TestJcmdConfigure { try { JcmdHelper.jcmd("JFR.configure", REPOSITORYPATH_SETTING_1); - SafePath initialPath = Repository.getRepository().getRepositoryPath(); + Path initialPath = Repository.getRepository().getRepositoryPath(); JcmdHelper.jcmd("JFR.configure", REPOSITORYPATH_SETTING_1); - SafePath samePath = Repository.getRepository().getRepositoryPath(); + Path samePath = Repository.getRepository().getRepositoryPath(); Asserts.assertTrue(samePath.equals(initialPath)); List lines = Files.readAllLines(Paths.get(JFR_UNIFIED_LOG_FILE)); Asserts.assertTrue(lines.stream().anyMatch(l->l.contains(findWhat))); JcmdHelper.jcmd("JFR.configure", REPOSITORYPATH_SETTING_2); - SafePath changedPath = Repository.getRepository().getRepositoryPath(); + Path changedPath = Repository.getRepository().getRepositoryPath(); Asserts.assertFalse(changedPath.equals(initialPath)); diff --git a/test/jdk/jdk/jfr/jvm/MyCommitRegisteredFalseEvent.java b/test/jdk/jdk/jfr/jvm/MyCommitRegisteredFalseEvent.java index d09d3067daf..5da979ad645 100644 --- a/test/jdk/jdk/jfr/jvm/MyCommitRegisteredFalseEvent.java +++ b/test/jdk/jdk/jfr/jvm/MyCommitRegisteredFalseEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -28,7 +28,7 @@ import jdk.jfr.Registered; @Registered(false) public class MyCommitRegisteredFalseEvent extends E implements Runnable { public void myCommit() { - PlaceholderEventWriterFactory.getEventWriter(4711L); + PlaceholderEventWriter.getEventWriter(); throw new RuntimeException("Should not reach here"); } diff --git a/test/jdk/jdk/jfr/jvm/MyCommitRegisteredTrueEvent.java b/test/jdk/jdk/jfr/jvm/MyCommitRegisteredTrueEvent.java index 87014bcd72b..0af8a8f41cc 100644 --- a/test/jdk/jdk/jfr/jvm/MyCommitRegisteredTrueEvent.java +++ b/test/jdk/jdk/jfr/jvm/MyCommitRegisteredTrueEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -28,7 +28,7 @@ import jdk.jfr.Registered; @Registered(true) public class MyCommitRegisteredTrueEvent extends E implements Runnable { public void myCommit() { - PlaceholderEventWriterFactory.getEventWriter(4711L); + PlaceholderEventWriter.getEventWriter(); throw new RuntimeException("Should not reach here"); } diff --git a/test/jdk/jdk/jfr/jvm/NonEvent.java b/test/jdk/jdk/jfr/jvm/NonEvent.java index 9134d25c08c..e98d995acdb 100644 --- a/test/jdk/jdk/jfr/jvm/NonEvent.java +++ b/test/jdk/jdk/jfr/jvm/NonEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -25,7 +25,7 @@ package jdk.jfr.jvm; // Class used by TestGetEventWriter public class NonEvent implements Runnable { public void commit() { - PlaceholderEventWriter ew = PlaceholderEventWriterFactory.getEventWriter(4711L); + PlaceholderEventWriter ew = PlaceholderEventWriter.getEventWriter();; throw new RuntimeException("Should not reach here " + ew); } diff --git a/test/jdk/jdk/jfr/jvm/PlaceholderEventWriter.java b/test/jdk/jdk/jfr/jvm/PlaceholderEventWriter.java index 8f0c5433347..87cffc51275 100644 --- a/test/jdk/jdk/jfr/jvm/PlaceholderEventWriter.java +++ b/test/jdk/jdk/jfr/jvm/PlaceholderEventWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -30,4 +30,8 @@ package jdk.jfr.jvm; // will be replaced with "jdk.jfr.internal.event.EventWriter" public class PlaceholderEventWriter { + public static PlaceholderEventWriter getEventWriter() { + return null; + } + } diff --git a/test/jdk/jdk/jfr/jvm/PlaceholderEventWriterFactory.java b/test/jdk/jdk/jfr/jvm/PlaceholderEventWriterFactory.java deleted file mode 100644 index 8083bc16a53..00000000000 --- a/test/jdk/jdk/jfr/jvm/PlaceholderEventWriterFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2022, 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. - */ -package jdk.jfr.jvm; - -// Purpose of this class is to have something to -// statically link against for TestGetEventWriter. -// -// When the class is loaded "jdk.jfr.jvm.PlaceholderEventWriterFactory" -// will be replaced with "jdk.jfr.internal.event.EventWriterFactory" -public class PlaceholderEventWriterFactory { - - public static PlaceholderEventWriter getEventWriter(long value) { - throw new RuntimeException("Test error, PlaceholderEventWriterFactory class should have been replaced with EventWriterFactory"); - } -} diff --git a/test/jdk/jdk/jfr/jvm/RegisteredFalseEvent.java b/test/jdk/jdk/jfr/jvm/RegisteredFalseEvent.java index 6174bace866..d20a0454500 100644 --- a/test/jdk/jdk/jfr/jvm/RegisteredFalseEvent.java +++ b/test/jdk/jdk/jfr/jvm/RegisteredFalseEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -28,7 +28,7 @@ import jdk.jfr.Registered; @Registered(false) public class RegisteredFalseEvent extends E { public void commit() { - PlaceholderEventWriterFactory.getEventWriter(4711L); + PlaceholderEventWriter.getEventWriter(); throw new RuntimeException("Should not reach here"); } } \ No newline at end of file diff --git a/test/jdk/jdk/jfr/jvm/RegisteredTrueEvent.java b/test/jdk/jdk/jfr/jvm/RegisteredTrueEvent.java index 3fe2ce8a119..fb2964e68e9 100644 --- a/test/jdk/jdk/jfr/jvm/RegisteredTrueEvent.java +++ b/test/jdk/jdk/jfr/jvm/RegisteredTrueEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -28,7 +28,7 @@ import jdk.jfr.Registered; @Registered(true) public class RegisteredTrueEvent extends E { public void commit() { - PlaceholderEventWriterFactory.getEventWriter(4711L); + PlaceholderEventWriter.getEventWriter(); throw new RuntimeException("Should not reach here"); } } \ No newline at end of file diff --git a/test/jdk/jdk/jfr/jvm/StaticCommitEvent.java b/test/jdk/jdk/jfr/jvm/StaticCommitEvent.java index 6adeb6cb9c5..8c07c5bf9b6 100644 --- a/test/jdk/jdk/jfr/jvm/StaticCommitEvent.java +++ b/test/jdk/jdk/jfr/jvm/StaticCommitEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -30,7 +30,7 @@ public class StaticCommitEvent implements Runnable { int value; public static void commit(long start, long duration, String message, int value) { - PlaceholderEventWriterFactory.getEventWriter(4711L); + PlaceholderEventWriter.getEventWriter(); throw new RuntimeException("Should not reach here"); } diff --git a/test/jdk/jdk/jfr/jvm/TestGetEventWriter.java b/test/jdk/jdk/jfr/jvm/TestGetEventWriter.java index 298114b14e1..7920678b7f0 100644 --- a/test/jdk/jdk/jfr/jvm/TestGetEventWriter.java +++ b/test/jdk/jdk/jfr/jvm/TestGetEventWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -46,7 +46,6 @@ import jdk.vm.ci.runtime.JVMCI; * jdk.internal.vm.ci/jdk.vm.ci.runtime * * @compile PlaceholderEventWriter.java - * @compile PlaceholderEventWriterFactory.java * @compile E.java * @compile NonEvent.java * @compile RegisteredTrueEvent.java @@ -80,7 +79,6 @@ import jdk.vm.ci.runtime.JVMCI; * jdk.internal.vm.ci/jdk.vm.ci.runtime * * @compile PlaceholderEventWriter.java - * @compile PlaceholderEventWriterFactory.java * @compile E.java * @compile NonEvent.java * @compile RegisteredTrueEvent.java @@ -105,10 +103,10 @@ public class TestGetEventWriter { InitializationEvent e = new InitializationEvent(); e.commit(); } - // Make sure EventWriterFactory can be accessed. - Class clazz = Class.forName("jdk.jfr.internal.event.EventWriterFactory"); + // Make sure EventWriter class can be accessed. + Class clazz = Class.forName("jdk.jfr.internal.event.EventWriter"); if (clazz == null) { - throw new Exception("Test error, not able to access jdk.jfr.internal.event.EventWriterFactory class"); + throw new Exception("Test error, not able to access jdk.jfr.internal.event.EventWriter class"); } testRegisteredTrueEvent(); testRegisteredFalseEvent(); @@ -122,7 +120,7 @@ public class TestGetEventWriter { // The class does not inherit jdk.jfr.Event and, as such, does not implement the // API. It has its own stand-alone "commit()V", which is not an override, that - // attempts to resolve and link against EventWriterFactory. This user implementation + // attempts to resolve and link against EventWriter. This user implementation // is not blessed for linkage. private static void testNonEvent() throws Throwable { Runnable e = newEventObject("NonEvent"); @@ -178,7 +176,7 @@ public class TestGetEventWriter { } // The user has implemented another method, "myCommit()V", not an override nor - // overload. that attempts to resolve and link EventWriterFactory. This will fail, + // overload. that attempts to resolve and link EventWriter. This will fail, // because "myCommit()V" is not blessed for linkage. private static void testMyCommitRegisteredTrue() throws Throwable { Runnable e = newEventObject("MyCommitRegisteredTrueEvent"); @@ -230,10 +228,9 @@ public class TestGetEventWriter { public void myCommit() throws Throwable { try { Class ew = Class.forName("jdk.jfr.internal.event.EventWriter"); - MethodType t = MethodType.methodType(ew, List.of(long.class)); - Class factory = Class.forName("jdk.jfr.internal.event.EventWriterFactory"); - MethodHandle mh = MethodHandles.lookup().findStatic(factory, "getEventWriter", t); - mh.invoke(Long.valueOf(4711)); // throws IllegalAccessException + MethodType t = MethodType.methodType(ew, List.of()); + MethodHandle mh = MethodHandles.lookup().findStatic(ew, "getEventWriter", t); + mh.invoke(); // throws IllegalAccessException } catch (ClassNotFoundException | SecurityException e) { throw new RuntimeException(e); } @@ -262,8 +259,8 @@ public class TestGetEventWriter { public void myCommit() throws Throwable { Class c; try { - c = Class.forName("jdk.jfr.internal.event.EventWriterFactory"); - Method m = c.getMethod("getEventWriter", new Class[] {long.class}); + c = Class.forName("jdk.jfr.internal.event.EventWriter"); + Method m = c.getMethod("getEventWriter", new Class[0]); m.invoke(null, Long.valueOf(4711)); // throws InternalError } catch (ClassNotFoundException | SecurityException e) { throw new RuntimeException(e); @@ -283,7 +280,7 @@ public class TestGetEventWriter { } catch (InternalError ie) { if (ie.getCause() instanceof IllegalAccessException iaex) { if (iaex.getCause() instanceof IllegalAccessError iae) { - if (iae.getMessage().contains("getEventWriter(long)")) { + if (iae.getMessage().contains("getEventWriter()")) { // OK, as expected return; } @@ -345,7 +342,6 @@ public class TestGetEventWriter { byte[] bytes = is.readAllBytes(); is.close(); bytes = replace(bytes, "jdk/jfr/jvm/E", "jdk/jfr/Event"); - bytes = replace(bytes, "jdk/jfr/jvm/PlaceholderEventWriterFactory", "jdk/jfr/internal/event/EventWriterFactory"); bytes = replace(bytes, "jdk/jfr/jvm/PlaceholderEventWriter", "jdk/jfr/internal/event/EventWriter"); BytesClassLoader bc = new BytesClassLoader(bytes, fullName); Class clazz = bc.loadClass(fullName); @@ -372,7 +368,7 @@ public class TestGetEventWriter { } /** - * Checks that JVMCI prevents unblessed access to {@code EventWriterFactory.getEventWriter(long)}. + * Checks that JVMCI prevents unblessed access to {@code EventWriter.getEventWriter()}. */ private static void checkJVMCI(Class eventClass, String commitName) throws Throwable { MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess(); @@ -380,7 +376,7 @@ public class TestGetEventWriter { ConstantPool cp = commit.getConstantPool(); // Search for first INVOKESTATIC instruction in commit method which is expected - // to be the call to jdk.jfr.internal.event.EventWriterFactory.getEventWriter(long). + // to be the call to jdk.jfr.internal.event.EventWriter.getEventWriter(). final int INVOKESTATIC = 184; byte[] code = commit.getCode(); for (int bci = 0; bci < code.length; bci++) { diff --git a/test/jdk/jdk/jfr/tool/TestAssemble.java b/test/jdk/jdk/jfr/tool/TestAssemble.java index ccc95498de4..2ac90b535a5 100644 --- a/test/jdk/jdk/jfr/tool/TestAssemble.java +++ b/test/jdk/jdk/jfr/tool/TestAssemble.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -35,7 +35,6 @@ import jdk.jfr.Recording; import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.consumer.RecordingFile; import jdk.jfr.internal.Repository; -import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; @@ -80,7 +79,7 @@ public class TestAssemble { expectedCount += countEventInRecording(tmp); } - SafePath repository = Repository.getRepository().getRepositoryPath(); + Path repository = Repository.getRepository().getRepositoryPath(); Path destinationPath = Paths.get("reconstructed.jfr"); String directory = repository.toString();