Reputation: 67
I have a question about Java 8 and the Garbage Collection we have a problem with an application that used to run on Java 6 with no problems and now we are having problems with Intermittent Printing the Host sends to the Applications Print messages and they work most of the time however based on the Logs it looks like when the Printer message is sent to the PrintSystem Class ( run as a separate thread ) its not responding. In doing some reading about the GC and strong and weak references it seems that the way that the PrintSystem send messages is like this
PrintSystem.getInstance().printMessage(message);
So it is possible that Java 8 is GC'ing the PrintSystem Thread due to differences between Java 6 and 8 ? Also the code was recompiled to run for Java 8, I am wondering if it should still be compiled for Java 6 and just run it on Java 8 ( if that makes sense )
Log Data 07Jan 14:59:38.037 communications.headers.PLMHeader.PLMMessage() INFO userData is 25 bytes
07Jan 14:59:38.038 communications.headers.PLMHeader.PLMMessage() INFO userData is: Test Message
07Jan 14:59:38.038 communications.ums.UMSWorker.run() INFO UMS Worker Active
07Jan 14:59:38.038 communications.ums.UMSWorker.run() INFO Received Unsolicited Message...
07Jan 14:59:38.038 communications.ums.UMSWorker.run() INFO Sending Message to print system ( Sent from UMSWorker Thread Should have had a PrintSystem Response with 100ms)
07 Jan 2019 15:00:19.365 communications.ums.UMSWorker.setAceNetHeader() INFO Data is: (41seconds before next message and its unrelated)
public void printMessage(Object message) throws Exception
{
if (!initialized)
throw new Exception("DEBUG: Print System not initialized!");
try
{
synchronized(this)
{
printList.add(message); // LinkedList
this.notify();
}
LogManager.traceMessage(this,"DEBUG: PrintSystem.PrintMessage()",
"printList Size : " + printList.size());
}
catch (Exception e)
{
LogManager.traceMessage(this,"DEBUG: PrintSystem.PrintMessage() ",
"Exception : " + e);
}
}
And this is the PrintSystem run() that waits / loops to read the printList
public void run()
{
Object message = null;
while (true)
{
try
{
synchronized(this)
{
this.wait(2500);
}
}
catch (Exception e) {}
while (!printList.isEmpty())
{
synchronized(this)
{
message = printList.removeFirst();
}
int printed = printPLMMessage((PLMHeader) message);
PLMHeader ackHeader = generatePrinterAck((PLMHeader)
message,printed);
Communications.getInstance().ack(ackHeader);
}
}
Thanks
Upvotes: 1
Views: 484
Reputation: 96385
I suspect this is not a GC issue. I think it’s a defective code issue.
The code adds things to printList with a lock held but the code reading from the printList doesn’t have the lock held when it reads. That makes this code insufficiently synchronized, so there are no guarantees about the visibility of updates to printList for the reading thread.
Apparently you got lucky previously and this code worked by accident. When you upgrade Java one of the things you get is better optimizations, that do fancy things like figuring out when they can delay updating caches or when they can rule out having to execute some code at all, and the decisions about when to invoke these optimizations have to assume the code they’re applied to is sufficiently synchronized. If the code isn’t then the optimizations can get applied in some way that isn’t what you want.
Upvotes: 2