8297976: Remove sun.net.ProgressMonitor and related classes

8240275: Occasional errors in HttpURLConnection due to race with GC

Reviewed-by: jpai, dfuchs, michaelm
This commit is contained in:
Daniel Jeliński 2022-12-07 08:56:10 +00:00
parent 085f96cb1a
commit 27bbe7be2c
14 changed files with 313 additions and 894 deletions

View file

@ -27,7 +27,6 @@ package sun.net.www;
import java.io.*;
import java.util.concurrent.locks.ReentrantLock;
import sun.net.ProgressSource;
import sun.net.www.http.ChunkedInputStream;
@ -42,19 +41,13 @@ public class MeteredStream extends FilterInputStream {
protected long count = 0;
protected long markedCount = 0;
protected int markLimit = -1;
protected ProgressSource pi;
private final ReentrantLock readLock = new ReentrantLock();
public MeteredStream(InputStream is, ProgressSource pi, long expected)
public MeteredStream(InputStream is, long expected)
{
super(is);
this.pi = pi;
this.expected = expected;
if (pi != null) {
pi.updateProgress(0, expected);
}
}
private final void justRead(long n) throws IOException {
@ -81,9 +74,6 @@ public class MeteredStream extends FilterInputStream {
markLimit = -1;
}
if (pi != null)
pi.updateProgress(count, expected);
if (isMarked()) {
return;
}
@ -170,8 +160,6 @@ public class MeteredStream extends FilterInputStream {
lock();
try {
if (closed) return;
if (pi != null)
pi.finishTracking();
closed = true;
in.close();
@ -241,17 +229,4 @@ public class MeteredStream extends FilterInputStream {
public final boolean isLockHeldByCurrentThread() {
return readLock.isHeldByCurrentThread();
}
@SuppressWarnings("removal")
protected void finalize() throws Throwable {
try {
close();
if (pi != null)
pi.close();
}
finally {
// Call super class
super.finalize();
}
}
}

View file

@ -34,7 +34,6 @@ import java.util.Properties;
import java.util.concurrent.locks.ReentrantLock;
import sun.net.NetworkClient;
import sun.net.ProgressSource;
import sun.net.www.MessageHeader;
import sun.net.www.HeaderParser;
import sun.net.www.MeteredStream;
@ -741,7 +740,7 @@ public class HttpClient extends NetworkClient {
/** Parse the first line of the HTTP request. It usually looks
something like: {@literal "HTTP/1.0 <number> comment\r\n"}. */
public boolean parseHTTP(MessageHeader responses, ProgressSource pi, HttpURLConnection httpuc)
public boolean parseHTTP(MessageHeader responses, HttpURLConnection httpuc)
throws IOException {
/* If "HTTP/*" is found in the beginning, return true. Let
* HttpURLConnection parse the mime header itself.
@ -758,7 +757,7 @@ public class HttpClient extends NetworkClient {
serverInput = new HttpCaptureInputStream(serverInput, capture);
}
serverInput = new BufferedInputStream(serverInput);
return (parseHTTPHeader(responses, pi, httpuc));
return (parseHTTPHeader(responses, httpuc));
} catch (SocketTimeoutException stex) {
// We don't want to retry the request when the app. sets a timeout
// but don't close the server if timeout while waiting for 100-continue
@ -785,7 +784,7 @@ public class HttpClient extends NetworkClient {
checkTunneling(httpuc);
afterConnect();
writeRequests(requests, poster);
return parseHTTP(responses, pi, httpuc);
return parseHTTP(responses, httpuc);
}
}
throw e;
@ -805,7 +804,7 @@ public class HttpClient extends NetworkClient {
}
}
private boolean parseHTTPHeader(MessageHeader responses, ProgressSource pi, HttpURLConnection httpuc)
private boolean parseHTTPHeader(MessageHeader responses, HttpURLConnection httpuc)
throws IOException {
/* If "HTTP/*" is found in the beginning, return true. Let
* HttpURLConnection parse the mime header itself.
@ -951,7 +950,7 @@ public class HttpClient extends NetworkClient {
checkTunneling(httpuc);
afterConnect();
writeRequests(requests, poster);
return parseHTTP(responses, pi, httpuc);
return parseHTTP(responses, httpuc);
}
}
throw new SocketException("Unexpected end of file from server");
@ -994,7 +993,7 @@ public class HttpClient extends NetworkClient {
|| (code >= 102 && code <= 199)) {
logFinest("Ignoring interim informational 1xx response: " + code);
responses.reset();
return parseHTTPHeader(responses, pi, httpuc);
return parseHTTPHeader(responses, httpuc);
}
long cl = -1;
@ -1067,11 +1066,6 @@ public class HttpClient extends NetworkClient {
// In this case, content length is well known, so it is okay
// to wrap the input stream with KeepAliveStream/MeteredStream.
if (pi != null) {
// Progress monitor is enabled
pi.setContentType(responses.findValue("content-type"));
}
// If disableKeepAlive == true, the client will not be returned
// to the cache. But we still need to use a keepalive stream to
// allow the multi-message authentication exchange on the connection
@ -1079,39 +1073,13 @@ public class HttpClient extends NetworkClient {
if (useKeepAliveStream) {
// Wrap KeepAliveStream if keep alive is enabled.
logFinest("KeepAlive stream used: " + url);
serverInput = new KeepAliveStream(serverInput, pi, cl, this);
serverInput = new KeepAliveStream(serverInput, cl, this);
failedOnce = false;
}
else {
serverInput = new MeteredStream(serverInput, pi, cl);
serverInput = new MeteredStream(serverInput, cl);
}
}
else if (cl == -1) {
// In this case, content length is unknown - the input
// stream would simply be a regular InputStream or
// ChunkedInputStream.
if (pi != null) {
// Progress monitoring is enabled.
pi.setContentType(responses.findValue("content-type"));
// Wrap MeteredStream for tracking indeterministic
// progress, even if the input stream is ChunkedInputStream.
serverInput = new MeteredStream(serverInput, pi, cl);
}
else {
// Progress monitoring is disabled, and there is no
// need to wrap an unknown length input stream.
// ** This is an no-op **
}
}
else {
if (pi != null)
pi.finishTracking();
}
return ret;
}

View file

@ -27,7 +27,6 @@ package sun.net.www.http;
import java.io.*;
import sun.net.ProgressSource;
import sun.net.www.MeteredStream;
import jdk.internal.misc.InnocuousThread;
@ -56,8 +55,8 @@ class KeepAliveStream extends MeteredStream implements Hurryable {
/**
* Constructor
*/
public KeepAliveStream(InputStream is, ProgressSource pi, long expected, HttpClient hc) {
super(is, pi, expected);
public KeepAliveStream(InputStream is, long expected, HttpClient hc) {
super(is, expected);
this.hc = hc;
}
@ -101,9 +100,6 @@ class KeepAliveStream extends MeteredStream implements Hurryable {
hc.finished();
}
} finally {
if (pi != null)
pi.finishTracking();
if (!queuedForCleanup) {
// nulling out the underlying inputstream as well as
// httpClient to let gc collect the memories faster

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 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
@ -36,7 +36,6 @@ import java.net.FileNameMap;
import java.io.*;
import java.text.Collator;
import java.security.Permission;
import sun.net.*;
import sun.net.www.*;
import java.util.*;
import java.text.SimpleDateFormat;
@ -82,15 +81,7 @@ public class FileURLConnection extends URLConnection {
throw new FileNotFoundException(filename + " exists, but is not accessible");
files = Arrays.<String>asList(fileList);
} else {
is = new BufferedInputStream(new FileInputStream(filename));
// Check if URL should be metered
boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, "GET");
if (meteredInput) {
ProgressSource pi = new ProgressSource(url, "GET", file.length());
is = new MeteredStream(is, pi, file.length());
}
}
} catch (IOException e) {
throw e;

View file

@ -56,8 +56,6 @@ import sun.net.www.URLConnection;
import sun.net.www.protocol.http.HttpURLConnection;
import sun.net.ftp.FtpClient;
import sun.net.ftp.FtpProtocolException;
import sun.net.ProgressSource;
import sun.net.ProgressMonitor;
import sun.net.www.ParseUtil;
import sun.security.action.GetPropertyAction;
@ -466,17 +464,7 @@ public class FtpURLConnection extends URLConnection {
// Wrap input stream with MeteredStream to ensure read() will always return -1
// at expected length.
// Check if URL should be metered
boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, "GET");
ProgressSource pi = null;
if (meteredInput) {
pi = new ProgressSource(url, "GET", l);
pi.beginTracking();
}
is = new MeteredStream(is, pi, l);
is = new MeteredStream(is, l);
}
} catch (Exception e) {
e.printStackTrace();

View file

@ -67,7 +67,8 @@ import java.util.Set;
import java.util.StringJoiner;
import jdk.internal.access.JavaNetHttpCookieAccess;
import jdk.internal.access.SharedSecrets;
import sun.net.*;
import sun.net.NetProperties;
import sun.net.NetworkClient;
import sun.net.util.IPAddressUtil;
import sun.net.www.*;
import sun.net.www.http.HttpClient;
@ -384,9 +385,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
String serverAuthKey, proxyAuthKey;
/* Progress source */
protected ProgressSource pi;
/* all the response headers we get back */
private MessageHeader responses;
/* the stream _from_ the server */
@ -1331,7 +1329,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
}
try {
http.parseHTTP(responses, pi, this);
http.parseHTTP(responses, this);
} catch (SocketTimeoutException se) {
if (!enforceTimeOut) {
throw se;
@ -1662,14 +1660,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
return cachedInputStream;
}
// Check if URL should be metered
boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, method);
if (meteredInput) {
pi = new ProgressSource(url, method);
pi.beginTracking();
}
/* REMIND: This exists to fix the HttpsURLConnection subclass.
* Hotjava needs to run on JDK1.1FCS. Do proper fix once a
* proper solution for SSL can be found.
@ -1679,7 +1669,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
if (!streaming()) {
writeRequests();
}
http.parseHTTP(responses, pi, this);
http.parseHTTP(responses, this);
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine(responses.toString());
}
@ -1943,10 +1933,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
respCode == HTTP_NOT_MODIFIED ||
respCode == HTTP_NO_CONTENT) {
if (pi != null) {
pi.finishTracking();
pi = null;
}
http.finished();
http = null;
inputStream = new EmptyInputStream();
@ -2166,9 +2152,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
sendCONNECTRequest();
responses.reset();
// There is no need to track progress in HTTP Tunneling,
// so ProgressSource is null.
http.parseHTTP(responses, null, this);
http.parseHTTP(responses, this);
/* Log the response to the CONNECT */
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
@ -3045,10 +3029,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
private void disconnectInternal() {
responseCode = -1;
inputStream = null;
if (pi != null) {
pi.finishTracking();
pi = null;
}
if (http != null) {
http.closeServer();
http = null;
@ -3062,10 +3042,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
public void disconnect() {
responseCode = -1;
if (pi != null) {
pi.finishTracking();
pi = null;
}
if (http != null) {
/*