URLConnection bug?

G

Guest

The Microsoft JVM seems to have a bug reading multiple URLs.

My test applet opens URLs in this sequence:
1. A URL that returns a basically empty HTML page
2. A URL that streams data for 2 seconds.
3. The same URL from step 1.
The problem is that #3 returns the tail end of #2's data instead of the
same data as #1, in spite of the fact that I close the InputStream,
call the garbage collector, and run the finalizers.

To see this in action, open
http://test.stream.wallst.com/JreBugTest.htm
and click the 'Go' button. Output will display in the applet and
also in the Java console.

This only occurs with Microsoft's JVM, not Sun's or others I've tried.
Am I missing something, or is there some other way to close a URLConnection?

Source code for the applet and isapi streaming dll are included in
the JAR file, and appended here as well:

---------- applet source ------------
import java.awt.*;
import java.applet.*;
import java.net.*;
import java.io.*;

public class datatest extends Applet
{
java.awt.Button button1 = new java.awt.Button();
StringBuffer m_s1 = new StringBuffer(),
m_s2 = new StringBuffer();

// Called when 'Go' button is pressed
class Listener implements java.awt.event.ActionListener {
public void actionPerformed(java.awt.event.ActionEvent event) {
m_s1.setLength(0); m_s2.setLength(0); repaint();
final String sBase = getCodeBase().getHost(), sFile = getCodeBase().getFile();
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

// Demonstrate different output from 2 calls to empty.htm
for (int i=0; i<2; ++i) {
System.gc(); System.runFinalization();

////////////////////////////////////////////////////////////////
// Get HTML data from empty.htm
////////////////////////////////////////////////////////////////
String sHtmlUrl = "http://" + sBase + sFile + "empty.htm";
System.out.println(getHtmlData(i==0 ? m_s1 : m_s2, sHtmlUrl));

////////////////////////////////////////////////////////////////
// Get partial stream data between 2 calls to empty.htm
////////////////////////////////////////////////////////////////
if (i == 0) {
String sStreamUrl = "http://" + sBase + sFile + "streamtest.dll";
StringBuffer s = new StringBuffer();
getHtmlData(s, sStreamUrl);
}
}
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}

StringBuffer getHtmlData(StringBuffer sContent, String sUrl) {
URL url = null;
try { url = new URL(sUrl); }
catch (MalformedURLException e) { exceptionReport(e); }

URLConnection conn = null;
try { conn = url.openConnection(); }
catch (IOException e) { exceptionReport(e); }

java.io.InputStream in = null;
try {
in = conn.getInputStream();
int nextByte;
for (int i=0; i<15 && (nextByte = in.read()) != -1; ++i)
sContent.append((char)nextByte);
}
catch (IOException e) { exceptionReport(e); }
finally {
if (in != null)
try { in.close(); }
catch (IOException e) { exceptionReport(e); }
}
return sContent;
}


void exceptionReport(Throwable e) {
System.out.println(e.getMessage());
e.printStackTrace(System.out);
}

public void init()
{
setLayout(null);
setSize(426,266);
button1.setLabel("Go");
add(button1);
button1.setBounds(36,12,60,24);

Listener lListener = new Listener();
button1.addActionListener(lListener);
}

public void paint(Graphics g) {
g.drawString("1st call to empty.htm: " + m_s1.toString(), 10, 120);
g.drawString("2nd call to empty.htm: " + m_s2.toString(), 10, 140);
g.drawString("Both should be: \"<html> <head> </head> <body>\"", 10, 160);
}
}
---------- isapi source ------------

#include "stdafx.h"
#include <stdio.h>

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}

BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer)
{
pVer->dwExtensionVersion = HSE_VERSION;
strncpy(pVer->lpszExtensionDesc, "Data streaming ISA", HSE_MAX_EXT_DLL_NAME_LEN);

return TRUE;
}
BOOL WINAPI TerminateExtension(DWORD dwFlags)
{
return TRUE;
}

void ProcessRequest(void* p)
{
EXTENSION_CONTROL_BLOCK* pECB = static_cast<EXTENSION_CONTROL_BLOCK*>(p);

// Send header
static const char szStatus[] = "200 OK",
szHeader[] = "Content-Type: application/octet-stream\r\n"
"Cache-Control: no-cache\r\n"
"Expires: Sat, 01 Jan 2000 00:00:00 GMT\r\n"
"\r\n";
static HSE_SEND_HEADER_EX_INFO header = { szStatus, szHeader, sizeof szStatus - 1, sizeof szHeader - 1, TRUE };
pECB->ServerSupportFunction(pECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, (void*)&header, NULL, NULL);

char buffer[20];
for (int i=0; i<20; ++i)
{
sprintf(buffer, "%02d|", i);
DWORD dw = strlen(buffer);
pECB->WriteClient(pECB->ConnID, (void*)buffer, &dw, HSE_IO_SYNC);
Sleep(100);
}
pECB->ServerSupportFunction(pECB->ConnID, HSE_REQ_DONE_WITH_SESSION, NULL, NULL, NULL);
}

DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK* pECB)
{
_beginthread(ProcessRequest, 0, pECB);
return HSE_STATUS_PENDING;
}
 
A

Andrew Thompson

in message | The Microsoft JVM seems to have a bug reading multiple URLs.

I wish I had a $ for every time I
heard 'Microsoft', 'JVM' and 'bug'
in the same sentence...

[ non-valid groups trimmed.. ]
 
L

Leo Gaggl

Andrew said:
I wish I had a $ for every time I
heard 'Microsoft', 'JVM' and 'bug'
in the same sentence...

And if you drop the 'JVM' you could stop working and join Billy G. on
the Fortune 500

:)
 
G

Guest

why use microsoft java ? isn't java an ibm stuff ?

The microsoft jvm/jre is installed on most windows PCs, and sun's
download is too big for our customers on modem connections.
 
G

Guest

The Microsoft JVM seems to have a bug reading multiple URLs.

My test applet opens URLs in this sequence:
1. A URL that returns a basically empty HTML page
2. A URL that streams data for 2 seconds.
3. The same URL from step 1.
The problem is that #3 returns the tail end of #2's data instead of the
same data as #1, in spite of the fact that I close the InputStream,
call the garbage collector, and run the finalizers.

To see this in action, open
http://test.stream.wallst.com/JreBugTest.htm
and click the 'Go' button. Output will display in the applet and
also in the Java console.

This only occurs with Microsoft's JVM, not Sun's or others I've tried.
Am I missing something, or is there some other way to close a URLConnection?

Source code for the applet and isapi streaming dll are included in
the JAR file, and appended here as well:

---------- applet source ------------
import java.awt.*;
import java.applet.*;
import java.net.*;
import java.io.*;

public class datatest extends Applet
{
java.awt.Button button1 = new java.awt.Button();
StringBuffer m_s1 = new StringBuffer(),
m_s2 = new StringBuffer();

// Called when 'Go' button is pressed
class Listener implements java.awt.event.ActionListener {
public void actionPerformed(java.awt.event.ActionEvent event) {
m_s1.setLength(0); m_s2.setLength(0); repaint();
final String sBase = getCodeBase().getHost(), sFile =
getCodeBase().getFile();
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

// Demonstrate different output from 2 calls to empty.htm
for (int i=0; i<2; ++i) {
System.gc(); System.runFinalization();

////////////////////////////////////////////////////////////////
// Get HTML data from empty.htm
////////////////////////////////////////////////////////////////
String sHtmlUrl = "http://" + sBase + sFile + "empty.htm";
System.out.println(getHtmlData(i==0 ? m_s1 : m_s2, sHtmlUrl));

////////////////////////////////////////////////////////////////
// Get partial stream data between 2 calls to empty.htm
////////////////////////////////////////////////////////////////
if (i == 0) {
String sStreamUrl = "http://" + sBase + sFile +
"streamtest.dll";
StringBuffer s = new StringBuffer();
getHtmlData(s, sStreamUrl);
}
}
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}

StringBuffer getHtmlData(StringBuffer sContent, String sUrl) {
URL url = null;
try { url = new URL(sUrl); }
catch (MalformedURLException e) { exceptionReport(e); }

URLConnection conn = null;
try { conn = url.openConnection(); }
catch (IOException e) { exceptionReport(e); }

java.io.InputStream in = null;
try {
in = conn.getInputStream();
int nextByte;
for (int i=0; i<15 && (nextByte = in.read()) != -1; ++i)
sContent.append((char)nextByte);
}
catch (IOException e) { exceptionReport(e); }
finally {
if (in != null)
try { in.close(); }
catch (IOException e) { exceptionReport(e); }
}
return sContent;
}


void exceptionReport(Throwable e) {
System.out.println(e.getMessage());
e.printStackTrace(System.out);
}

public void init()
{
setLayout(null);
setSize(426,266);
button1.setLabel("Go");
add(button1);
button1.setBounds(36,12,60,24);

Listener lListener = new Listener();
button1.addActionListener(lListener);
}

public void paint(Graphics g) {
g.drawString("1st call to empty.htm: " + m_s1.toString(), 10, 120);
g.drawString("2nd call to empty.htm: " + m_s2.toString(), 10, 140);
g.drawString("Both should be: \"<html> <head> </head> <body>\"",
10, 160);
}
}
---------- isapi source ------------
#include "stdafx.h"
#include <stdio.h>

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}

BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer)
{
pVer->dwExtensionVersion = HSE_VERSION;
strncpy(pVer->lpszExtensionDesc, "Data streaming ISA",
HSE_MAX_EXT_DLL_NAME_LEN);

return TRUE;
}
BOOL WINAPI TerminateExtension(DWORD dwFlags)
{
return TRUE;
}

void ProcessRequest(void* p)
{
EXTENSION_CONTROL_BLOCK* pECB = static_cast<EXTENSION_CONTROL_BLOCK*>(p);

// Send header
static const char szStatus[] = "200 OK",
szHeader[] = "Content-Type: application/octet-stream\r\n"
"Cache-Control: no-cache\r\n"
"Expires: Sat, 01 Jan 2000 00:00:00 GMT\r\n"
"\r\n";
static HSE_SEND_HEADER_EX_INFO header = { szStatus, szHeader, sizeof
szStatus - 1, sizeof szHeader - 1, TRUE };
pECB->ServerSupportFunction(pECB->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER_EX, (void*)&header, NULL, NULL);

char buffer[20];
for (int i=0; i<20; ++i)
{
sprintf(buffer, "%02d|", i);
DWORD dw = strlen(buffer);
pECB->WriteClient(pECB->ConnID, (void*)buffer, &dw, HSE_IO_SYNC);
Sleep(100);
}
pECB->ServerSupportFunction(pECB->ConnID, HSE_REQ_DONE_WITH_SESSION,
NULL, NULL, NULL);
}

DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK* pECB)
{
_beginthread(ProcessRequest, 0, pECB);
return HSE_STATUS_PENDING;
}
 
A

Andrew Thompson

in message | (e-mail address removed) (ppcdev) wrote:
| >why use microsoft java ? isn't java an ibm stuff ?
|
| The microsoft jvm/jre is installed on most windows PCs, and
sun's
| download is too big for our customers on modem connections.

That is unfortunate.

By the way. Sorry for diverting your original
thread, I noticed you had to resubmit it in
an effort not to let the question get lost in the
quagmire of MS bashing.

I am not _that_ experienced with applets
and URL connections, but if I have time
later I will have a look over it. (Never
attempted one with multiple connections..)

I hope you get an answer that
solves the problem.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,262
Messages
2,571,056
Members
48,769
Latest member
Clifft

Latest Threads

Top