Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

8320971: Use BufferedInputStream.buf directly when param of implTransferTo() is trusted #16879

Closed
wants to merge 25 commits into from

Conversation

stsypanov
Copy link
Contributor

@stsypanov stsypanov commented Nov 29, 2023

It looks like we can skip copying of byte[] in BufferedInputStream.implTransferTo() for OutputStreams residing in java.io.

See comment by @vlsi in https://github.com/openjdk/jdk/pull/10525/files#diff-e19c508d1bb6ee78697ecca66947c395adda0d9c49a85bf696e677ecbd977af1R612


Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue

Issue

  • JDK-8320971: Use BufferedInputStream.buf directly when param of implTransferTo() is trusted (Enhancement - P4)

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/16879/head:pull/16879
$ git checkout pull/16879

Update a local copy of the PR:
$ git checkout pull/16879
$ git pull https://git.openjdk.org/jdk.git pull/16879/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 16879

View PR using the GUI difftool:
$ git pr show -t 16879

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/16879.diff

Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented Nov 29, 2023

👋 Welcome back stsypanov! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk openjdk bot added the rfr Pull request is ready for review label Nov 29, 2023
@openjdk
Copy link

openjdk bot commented Nov 29, 2023

@stsypanov The following label will be automatically applied to this pull request:

  • core-libs

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added the core-libs core-libs-dev@openjdk.org label Nov 29, 2023
@mlbridge
Copy link

mlbridge bot commented Nov 29, 2023

Comment on lines 646 to 653
// trust all OutputStreams from java.io
if (out.getClass().getPackageName() == BufferedInputStream.class.getPackageName()) {
out.write(getBufIfOpen(), pos, count);
} else {
// Prevent poisoning and leaking of buf
byte[] buffer = Arrays.copyOfRange(getBufIfOpen(), pos, count);
out.write(buffer);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// trust all OutputStreams from java.io
if (out.getClass().getPackageName() == BufferedInputStream.class.getPackageName()) {
out.write(getBufIfOpen(), pos, count);
} else {
// Prevent poisoning and leaking of buf
byte[] buffer = Arrays.copyOfRange(getBufIfOpen(), pos, count);
out.write(buffer);
}
out.write(getBufIfOpen(), pos, count);

What do you think of passing the buffer as is?
ByteArrayInputStream passes the buffer without extra copies anyway:

public synchronized long transferTo(OutputStream out) throws IOException {
int len = count - pos;
if (len > 0) {
int nwritten = 0;
while (nwritten < len) {
int nbyte = Integer.min(len - nwritten, MAX_TRANSFER_SIZE);
out.write(buf, pos, nbyte);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of passing the buffer as is?

No, it should only do for trusted targets. BAIS has an issue in that area that should be fixed.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The buffer in question is protected, so any subclass can directly access it. In other words, untrusted code can easily acoess the buffer, and it does not sound fair to add extra overhead to the method which was created for the performance reasons.

Does copyOfRange do any good here? Do you mean JDK should copy every buffer it passes to non-JDK code?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The buffer in question is protected, so any subclass can directly access it. In other words, untrusted code can easily acoess the buffer, and it does not sound fair to add extra overhead to the method which was created for the performance reasons.

If something extends BIS then it has access to the protected fields, this isn't a concern here. Instead, the concern is about passing a reference to the target output stream.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vlsi Yes, unless the JRE comes up with read-only buffers all untrusted code should get copies of JRE-internal buffers only to provide buffer poisoning and spying data located beyond range limits. Subclasses are free to do what they want with the inherited buffer (it is their buffer implicitly), but target output stream might be an injected bad guy that we must not trust in any regard.

byte[] buffer = Arrays.copyOfRange(getBufIfOpen(), pos, count);
out.write(buffer);
// trust all OutputStreams from java.io
if (out.getClass().getPackageName() == BufferedInputStream.class.getPackageName()) {
Copy link
Contributor

@AlanBateman AlanBateman Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think Class::getPackageName documents that the returned String is intern so I wonder if the == check will lead to questions and suggestions of a bug. Classes with names starting with "java." can only be defined to the boot or platform class loader (details in the ClassLoader API docs) so you could just check if the package name equals "java.io". We of course first need to think through the implications of this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we only want to trust java.io or anything starting with java.*?

Copy link

@jmehrens jmehrens Nov 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think checking if the package is java.io is secure:

ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
BufferedInputStream bis = new BufferedInputStream(bais);
UntrustedOutputStream uos = new UntrustedOutputStream();
bis.transferTo(new java.io.DataOutputStream(uos)); 

You have to know that it is in the java.io package and it doesn't wrap another stream.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have to know that it is in the java.io package and it doesn't wrap another stream.

That is a good point. In the previous work on this override, we converged on the current implementation to not leak the internal byte[] to the target. It could be special cased for trusted targets but at the cost of auditing and complexity. So more thought needed on this, I don't think the current change can be integrated.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of adding OutputStream extends WritableByteChannel, so transferTo could be implemented with if (target instanceof WritableByteChannel) { target.write(ByteBuffer.wrap(buf, off, len).asReadOnly()); }?

Read-only byte buffer will not allow modifying the data in the buffer, it would eliminate buffer copies, and adding write(ByteBuffer) to OutputStream seems reasonable.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've created a draft change for OutputStream#write(ByteBuffer), and I have benchmarked several cases including ByteArrayInputStream.transferTo(BufferedOutputStream(ByteArrayOutputStream)), ByteArrayInputStream.transferTo(DataOutputStream(FileOutputStream)).

Benchmarks show there's improvement in both allocation rate and latency.

Read-only ByteBuffers can address poisoning concerns as non-jdk code can't peek into read-only arrays.

The write(ByteBuffer) approach supports cases like CheckedOutputStream, DataOutputStream which would be hard or impossible to optimize when passing naked byte arrays.

Here are the results: https://gist.github.com/vlsi/7f4411515a4f2dbb0925fffde92ccb1d
Here is the diff: vlsi/jdk@ce10844...write_bytebuffer

@mkarg , @bplb , @AlanBateman , could you please review OutputStream.write(ByteBuffer) approach?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vlsi This is a very interesting solution 🤩, but it opens a number of questions! 🤔 As a start, here are mine:

  • You propose a new public method (OutputStream.write(ByteBuffer)) as part of your solution. We need to discuss whether this is worth the effort to change all implementations (and to perceive acceptable performance, all custom authors need to optimize their custom classes, too). We also need to discuss whether we like the design choice that de facto the public API (not just the implementation) of the legacy IO domain (OutputStream) is now linked to the NIO domain (ByteBuffer) (which, IMHO, feels some kind of scary beyond ChannelOutputStream).
  • Just thinking loudly: I wonder if we could simplify the solution, or if we could turn parts of it into some generic byte[] readOnly(byte[]) utility.
  • I would like to know how much faster the solution with ByteBuffer is compared to Arrays.copyOfRange(): Is it really so huge that it is worth the additional trouble?
  • I would like to know how much slower the solution with ByteBuffer is compared to skipping Arrays.copyOfRange() for trusted cases (as you removed the skipping).
  • I would like to know the performance of custom streams, because your default implementation is filling a temporary byte array with a Java-implemented byte-by-byte loop, which IMHO would be rather painful compared to hardware-supported copyOrRange(), and it does that even in case of trusted targets.
  • @briangoetz Wouldn't we rather teach the Java language some day to provide native read-only arrays? That would be much faster, much better to read and implies less complex code for the end user.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While frozen arrays are on our radar, this is a significant lift, so unlikely to be coming all that soon.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose to separate this PR from Vladimir's proposal, so we can merge this PR first, and if we later see that Vladimir's changes are accepted, we can merge them ontop. Agreed everybody?

Copy link
Contributor

@mkarg mkarg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for further optimizing transferTo()! If you fix what Alan proposed, this PR LGTM! 👍

byte[] buffer = Arrays.copyOfRange(getBufIfOpen(), pos, count);
out.write(buffer);
// trust all OutputStreams from java.io
if (out.getClass().getPackageName() == BufferedInputStream.class.getPackageName()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we only want to trust java.io or anything starting with java.*?

@bplb
Copy link
Member

bplb commented Nov 30, 2023

If there is already test coverage of this area (I don't think there is), then the noreg-other label with a comment should be added to the issue. Otherwise, test coverage should be added, or some other noreg-* label added to the issue, if justified.

@ecki
Copy link
Contributor

ecki commented Nov 30, 2023

Did you review if all Java.* streams are safe?

There are a few stream adapters in sun.nio.ch, which would benefit this optimization too, unfortunately they wrap the arrays with ByteBuffer.wrap, I guess that’s not safe, so the package can’t be allowed?

@stsypanov
Copy link
Contributor Author

@ecki I've checked the streams in java.* and it looks like none of them modifies the incoming byte[]

@ecki
Copy link
Contributor

ecki commented Dec 1, 2023

@ecki I've checked the streams in java.* and it looks like none of them modifies the incoming byte[]

i think modification is not the problem, the querstion is if they get exposed to user code. (but yes the readonly ByteBuffer wrapper looks like a good thing to use more).

@vlsi
Copy link

vlsi commented Dec 1, 2023

@ecki , what do you think of using read-only ByteBuffer instead?

See #16879 (comment)

It looks like there might be OutputStream extends WritableByteChannel. Then we won't need to perform deep analysis.

@ecki
Copy link
Contributor

ecki commented Dec 1, 2023

@ecki , what do you think of using read-only ByteBuffer instead?

See #16879 (comment)

It looks like there might be OutputStream extends WritableByteChannel. Then we won't need to perform deep analysis.

i am not completely sure if exposing buffers is a problem in terms of dirty data and if thats an issue with those wrappers. Well honestly it cant be anissue since we dont have untrusted code, but I understand future undertakings need to take this into account (insert SecurityManager rant here :)

@jmehrens
Copy link

jmehrens commented Dec 2, 2023

I think it is safe to poison and leak this.buf only while we are holding the lock on the BufferedInputStream and while the stream is not required to remember any bytes. However, the current this.buf must clear out of bounds data to avoid sharing old data and must be freed from this stream before the lock is released to prevent tampering with the next locking call to BufferedInputStream.

private long implTransferTo(OutputStream out) throws IOException {
    byte[] buffer;
    if (getClass() == BufferedInputStream.class && markpos == -1) {
        int avail = count - pos;
        if (avail > 0) {
            byte[] buffer = getBufIfOpen(false);
            try {
                Arrays.fill(buffer, 0, pos, (byte) 0);
                Arrays.fill(buffer, count, buffer.length, (byte) 0);
                out.write(buffer, pos, count);
                return Math.addExact(avail, getInIfOpen().transferTo(out));
            } catch (ArithmeticException ignore) {
                return Long.MAX_VALUE;
            } finally { //forget current buffer as it was leaked and poisoned
                if (U.compareAndSetReference(this, BUF_OFFSET, buffer, EMPTY)) {
                    pos = count = 0;
                }
            }
        } else {
            return super.transferTo(out);
        }
    }

Thoughts?

@jmehrens
Copy link

jmehrens commented Dec 2, 2023

I think I'm just reliving #10525 (comment)

*
* @return true if the argument of {@link #write(byte[])}} and {@link #write(byte[], int, int)}} needn't be copied
*/
boolean trusted() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a strange construction. Any subclass could simply implement this as return true;. Where is the guard against this, and why not doing it that way?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically speaking, OutputStream is an abstract class, so this declaration of boolean trusted() is a package-protected method that will be visible and overridable only within JDK itself.
However, I agree it looks suspicious.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment on this method doesn't look right. The issue for BAIS is that its lifetime may be different to the byte[] that it wraps, think about use after the BAIS has been discarded. You don't want a sink keeping a reference to the byte[] even if it doesn't scribble on it.

Copy link
Contributor Author

@stsypanov stsypanov Dec 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkarg I guess the method can only be implemented by subclasses residing in the same package with OutputStream, right?

@AlanBateman fixed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stsypanov Yes but still it is just weird to ask any output stream if it is trusted. I mean, it feels just unsecure to ask: "Do you pretend to be trusted?" instead of "Do we trust you?". I could sleep better if this method would not be part of each OutputStream subclass. We should either move it back to the place where needed, or into some static utility like OutputStreams::isTrusted(OutputStream) (mind the plural!), or it should at least be final.

Copy link
Contributor

@ecki ecki Dec 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Deleted) the new version doesn’t have the issue (albeit now it’s rather complicated formulated) “If stream can be used by JCL callers without extra copies of the byte[] argument to write(). This is not over writeable by user code.”

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlike BAIS, the BufferedInputStream can wrap an untrusted InputStream. BIS.buf is passed directly to wrapped InputStream so I would assume that we would want to avoid exposing BIS.buf to the out parameter of transferTo. This way we know the input stream is not able to poison the output stream when a write is in progress.

I assume that the current small list of trusted classes are also immune to poison so I imagine this patch is safe. However, for any FilterInputStream we should either always use Arrays.copyOfRange because the input side can poison the output side or it needs a mirroring allow list for the target input stream to insure that the wrapped input stream is not poisoning the out parameter.

For instance, java.util.zip.CheckedOutputStream in theory could be added as trusted class as it doesn't leak or poison but, looking at the code it would appear that it is not immune to poison.

@stsypanov stsypanov marked this pull request as draft December 22, 2023 15:42
@openjdk openjdk bot removed the rfr Pull request is ready for review label Dec 22, 2023
if (!Arrays.equals(buf, bis.readAllBytes())) {
throw new RuntimeException("Internal buffer was modified");
}
var internalBuffer = bis.getClass().getDeclaredField("buf");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO you don't need to whitebox here, as the blackbox approach described by me earlier should be sufficient to assert the claim of this PR.

}
var internalBuffer = bis.getClass().getDeclaredField("buf");
internalBuffer.setAccessible(true);
if (!Arrays.equals(buf, Arrays.copyOf((byte[]) internalBuffer.get(bis), length))) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not testing the absence of a copy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but how could I intercept the argument of OutputStream.write() and check it's identity?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I wrote earlier today to Vladimir (see above) I actually do not see a solution for this, frankly spoken, as the interceptor would not be trusted. That's why I asked Brian for his ok to keep the test as-is. We need to wait for his judgement, as he is the reviewer, not me (I only try to give initial advice). My comment was more a hint for me to wait for Brian's judgement, less a request to you to fix this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bplb are you ok with the current implementation and its test?

@stsypanov stsypanov marked this pull request as ready for review December 28, 2023 15:05
@openjdk openjdk bot added the rfr Pull request is ready for review label Dec 28, 2023
* <li>does not leak a reference to the {@code byte[]} to non-trusted classes</li>
* <li>does not modify the contents of the {@code byte[]}</li>
* <li>{@code OutputStream.write(byte[], int, int)} write does not read the contents outside of the offset/length bounds</li>
* </ul>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation change looks fine, just a typo at L671 where it says "write write", I think you can shorten this to say that the write method doesn't read the contents outside of the offset/length bounds.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Can we somehow modify the test to make it white-box one? Maybe it's possible to measure memory allocation before and after method invocation in the way that we could use the difference as a proof of non-allocating invocation for trusted OutputStreams?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume you mean "to make it a blackbox"? Actually I do not see how we could do that reliably, as I already wrote recently.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

com.sun.management.ThreadMXBean#getCurrentThreadAllocatedBytes is reliable, isn't it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to its JavaDocs it only returns an approximation, whatever that means. And it is measuring memory, while I already explained that the aim of this PR IMHO is not to spare memory, but to spare time. I wonder why we do not simply merge this PR as-is to get the actual benefits integrated ASAP instead of holding the train by heating up this discussion again?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkarg apologies, of course I meant black box test.

@stsypanov
Copy link
Contributor Author

/integrate

@openjdk
Copy link

openjdk bot commented Dec 30, 2023

@stsypanov This pull request has not yet been marked as ready for integration.

@mkarg
Copy link
Contributor

mkarg commented Dec 30, 2023

@AlanBateman Kindly requesting your review. :-)

Copy link
Contributor

@AlanBateman AlanBateman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation changes looks fine, that's for taking all the feedback to get this one to a good place.

@bplb has been reviewing the test, I'll stay out of that and let Brian finish his review.

@openjdk
Copy link

openjdk bot commented Jan 2, 2024

@stsypanov This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8320971: Use BufferedInputStream.buf directly when param of implTransferTo() is trusted

Reviewed-by: alanb, bpb

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 21 new commits pushed to the master branch:

  • 51238c4: 8322503: Shenandoah: Clarify gc state usage
  • 9481d06: 8320343: Generate GIF images for AbstractButton/5049549/bug5049549.java
  • a5cf421: 8320360: ClassFile.parse: Some defect class files cause unexpected exceptions to be thrown
  • f9aec02: 8321540: ClassSignature.parseFrom() throws StringIndexOutOfBoundsException for invalid signatures
  • 7455b1b: 8322159: ThisEscapeAnalyzer crashes for erroneous code
  • d4fb308: 8317846: Typo in API documentation of classes IdentityHashMap
  • d786c49: 8322751: ZGC: Fix comments about marking roots
  • 5852f3e: 8322027: One XMLStreamException constructor fails to initialize cause
  • be0e1c7: 8297573: Parallel: Rename do_oop_nv to do_oop_work in subclasses of OopClosure
  • 7c1d481: 8322765: Eliminate -Wparentheses warnings in runtime code
  • ... and 11 more: https://git.openjdk.org/jdk/compare/c53f845ec9943c1bd59a7757cce431217aac2bdc...master

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

As you do not have Committer status in this project an existing Committer must agree to sponsor your change. Possible candidates are the reviewers of this PR (@AlanBateman, @bplb) but any other Committer may sponsor as well.

➡️ To flag this PR as ready for integration with the above commit message, type /integrate in a new comment. (Afterwards, your sponsor types /sponsor in a new comment to perform the integration).

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Jan 2, 2024
@bplb
Copy link
Member

bplb commented Jan 2, 2024

@bplb has been reviewing the test, I'll stay out of that and let Brian finish his review.

I think that the test looks all right, but the copyright might need to be changed to 2023, 2024 instead of just 2023 as it is a new file. The source file does not need 2024 if no changes have been made in the last two days.

@stsypanov
Copy link
Contributor Author

/integrate

@openjdk openjdk bot added the sponsor Pull request is ready to be sponsored label Jan 2, 2024
@openjdk
Copy link

openjdk bot commented Jan 2, 2024

@stsypanov
Your change (at version 8d15e74) is now ready to be sponsored by a Committer.

@bplb
Copy link
Member

bplb commented Jan 2, 2024

/sponsor

@openjdk
Copy link

openjdk bot commented Jan 2, 2024

Going to push as commit 38042ad.
Since your change was applied there have been 21 commits pushed to the master branch:

  • 51238c4: 8322503: Shenandoah: Clarify gc state usage
  • 9481d06: 8320343: Generate GIF images for AbstractButton/5049549/bug5049549.java
  • a5cf421: 8320360: ClassFile.parse: Some defect class files cause unexpected exceptions to be thrown
  • f9aec02: 8321540: ClassSignature.parseFrom() throws StringIndexOutOfBoundsException for invalid signatures
  • 7455b1b: 8322159: ThisEscapeAnalyzer crashes for erroneous code
  • d4fb308: 8317846: Typo in API documentation of classes IdentityHashMap
  • d786c49: 8322751: ZGC: Fix comments about marking roots
  • 5852f3e: 8322027: One XMLStreamException constructor fails to initialize cause
  • be0e1c7: 8297573: Parallel: Rename do_oop_nv to do_oop_work in subclasses of OopClosure
  • 7c1d481: 8322765: Eliminate -Wparentheses warnings in runtime code
  • ... and 11 more: https://git.openjdk.org/jdk/compare/c53f845ec9943c1bd59a7757cce431217aac2bdc...master

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot added the integrated Pull request has been integrated label Jan 2, 2024
@openjdk openjdk bot closed this Jan 2, 2024
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review sponsor Pull request is ready to be sponsored labels Jan 2, 2024
@openjdk
Copy link

openjdk bot commented Jan 2, 2024

@bplb @stsypanov Pushed as commit 38042ad.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

@stsypanov stsypanov deleted the 8320971 branch January 2, 2024 20:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core-libs core-libs-dev@openjdk.org integrated Pull request has been integrated
Development

Successfully merging this pull request may close these issues.

9 participants