This is a valid point, because I wasn’t sure that when the thread is
interrupted, I handled the first exception, and my thought was that all other
‘wait’ calls (maybe in other threads) should get the same exception as well.
And since I handled this exceptional case, I am restoring the interrupted
status in case if I don’t know how to handle this exception the second time.
} catch (InterruptedException e1) {
try {
mTracker.waitForID(id, 0);
} catch (InterruptedException e2) {
loadStatus = MediaTracker.ABORTED;
Thread.currentThread().interrupt();
}
If I restore the interrupted status BEFORE waitForID call, then this thread
will immoderately fail. Should I restore it AFTER, e.g.
} catch (InterruptedException e1) {
try {
mTracker.waitForID(id, 0);
Thread.currentThread().interrupt(); // <— Here?
} catch (InterruptedException e2) {
loadStatus = MediaTracker.ABORTED;
Thread.currentThread().interrupt();
}
Thanks,
Vlad
Sent from myPad
> On 28. Jan 2020, at 22:27, Jason Mehrens <[email protected]> wrote:
>
> I see. Well I would have to do some more digging and testing to make myself
> more knowledgeable on MediaTracker.
>
> Then the only bug in your current code is that you are not reasserting
> interrupted status of the current thread in the case e1 is raised and e2 is
> not. It is usually best to reassert the interrupted state at the end of the
> method.
>
> Jason
>
> ________________________________________
> From: Volodin, Vladislav <[email protected]>
> Sent: Tuesday, January 28, 2020 2:54 PM
> To: Jason Mehrens
> Cc: [email protected]
> Subject: Re: <Swing Dev> Remove System.out.println from ImageIcon.loadImage
>
> Hi Jason,
>
> I am not sure about the loop, because I don’t know if we can trust results
> from mTracker.statusID at the moment when an exceptional case occurs. For
> example, I was experimenting with the code and found out that the
> MediaTracker can spawn a thread to load the image, or might use the current
> thread, and the ABORTED state is never returned (I don’t even know how to
> raise this state). That is why I don’t even know if your loop will ever stop.
>
> In my solution, I give the second chance only, and in case if the execution
> was interrupted the second time, I explicitly assign the ABORTED state to
> loadStatus. If the user wants to load this image once again, he can create
> ImageIcon again (or even do this in a loop), or reinitialize it with a single
> method (I don’t remember its name).
>
> What do you think?
>
> Kind regards,
> Vlad
>
> Sent from myPad
>
>> On 28. Jan 2020, at 21:34, Jason Mehrens <[email protected]> wrote:
>>
>> Vlad,
>>
>> I assume you would want to wait in a loop and reassert the interrupt at the
>> end.
>>
>> ===
>> protected void loadImage(Image image) {
>> MediaTracker mTracker = getTracker();
>> synchronized(mTracker) {
>> int id = getNextID();
>>
>> mTracker.addImage(image, id);
>> boolean wasInterrupted = false;
>> try {
>> do {
>> try {
>> mTracker.waitForID(id, 0);
>> } catch (InterruptedException e) {
>> wasInterrupted = true;
>> }
>> loadStatus = mTracker.statusID(id, false);
>> } while (loadStatus == MediaTracker.LOADING);
>> mTracker.removeImage(image, id);
>>
>> width = image.getWidth(imageObserver);
>> height = image.getHeight(imageObserver);
>> } finally {
>> if (wasInterrupted) {
>> Thread.currentThread().interrupt();
>> }
>> }
>> }
>> }
>> ===
>>
>> Jason
>> ________________________________________
>> From: swing-dev <[email protected]> on behalf of Volodin,
>> Vladislav <[email protected]>
>> Sent: Monday, January 27, 2020 11:11 AM
>> To: Sergey Bylokhov
>> Cc: [email protected]
>> Subject: Re: <Swing Dev> Remove System.out.println from ImageIcon.loadImage
>>
>> Hello Sergey, and others,
>>
>> here is the patch (made with "git diff") in the attachment. I have read that
>> sometimes the attachments are lost. So here is my version with few comments
>> regarding my code. I decided to use your approach with a small improvement.
>> There is an excerpt of my patch.
>>
>> The idea is pretty simple:
>> 1. I create an empty gif 1x1;
>> 2. Initialize DefaultToolkit (I plan to interrupt the main thread, and if I
>> do not initialize the toolkit in advance, my test will fail at the beginning
>> 3. Interrupt the main thread
>> 4. Try to load the icon:
>>
>> import javax.swing.*;
>> import java.awt.*;
>>
>> public class imageIconInterrupted {
>> static byte[] EMPTY_GIF = new byte[]{
>> (byte) 0x47, (byte) 0x49, (byte) 0x46, (byte) 0x38, (byte) 0x39,
>> (byte) 0x61, (byte) 0x01, (byte) 0x00,
>> (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
>> (byte) 0x21, (byte) 0xF9, (byte) 0x04,
>> (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
>> (byte) 0x2C, (byte) 0x00, (byte) 0x00,
>> (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01,
>> (byte) 0x00, (byte) 0x00, (byte) 0x02
>> };
>>
>> public static void main(String[] args) throws Exception {
>> Toolkit ignoreToolkit = Toolkit.getDefaultToolkit();
>>
>> Thread.currentThread().interrupt();
>> ImageIcon iconInterrupt = new ImageIcon(EMPTY_GIF);
>> if (iconInterrupt.getImageLoadStatus() != MediaTracker.COMPLETE) {
>> throw new RuntimeException("Couldn't load GIF from bytes after
>> interruption");
>> }
>> }
>> }
>>
>> The code of loadImage I have changed as follows:
>> 1. I clear loadStatus for "finally" part;
>> 2. Check the interruption according to your comments;
>> 3. Change the status to ABORTED, if the interruption happened again (this
>> part I cannot test, because I cannot properly interrupt the thread whenever
>> I want. Multithreading is quite fragile there :( )
>> 4. update the status "interrupted" again;
>> 5. and then - finally block.
>>
>> protected void loadImage(Image image) {
>> ...
>> try {
>> loadStatus = 0;
>> mTracker.addImage(image, id);
>> mTracker.waitForID(id, 0);
>> } catch (InterruptedException e1) {
>> try {
>> mTracker.waitForID(id, 0);
>> } catch (InterruptedException e2) {
>> loadStatus = MediaTracker.ABORTED;
>> Thread.currentThread().interrupt();
>> }
>> } finally {
>> if (loadStatus == 0) {
>> loadStatus = mTracker.statusID(id, false);
>> }
>> mTracker.removeImage(image, id);
>> }
>>
>> P.S. if you think that my patch sounds fine, I will find a sponsor for the
>> bug report and the patch preparation, so you can review it later.
>> After the second attempt, my EMPTY_GIF was loaded successfully. The ABORTED
>> part it seems that I don't know if it has ever worked. My patch (in the
>> attachment) checks also the state ERROR for the URL that doesn't exist.
>> Something like:
>>
>> ImageIcon iconNotExist = new ImageIcon(new
>> URL("http://doesnt.exist.anywhere/1.gif")); // I am not sure if I spelled
>> this URL grammatically correct
>> if (iconNotExist.getImageLoadStatus() != MediaTracker.ERRORED) {
>> throw new RuntimeException("Got unexpected status from
>> non-existing GIF");
>> }
>>
>> Thanks to everyone.
>>
>> Kind regards,
>> Vlad
>>
>> -----Original Message-----
>> From: Sergey Bylokhov <[email protected]>
>> Sent: Dienstag, 21. Januar 2020 22:26
>> To: Volodin, Vladislav <[email protected]>
>> Cc: Jason Mehrens <[email protected]>; [email protected]
>> Subject: Re: <Swing Dev> Remove System.out.println from ImageIcon.loadImage
>>
>>>> On 1/21/20 1:14 pm, Volodin, Vladislav wrote:
>>> Hi all,
>>>
>>> If I am not mistaken, this method is called from the constructor and other
>>> methods. How long should we try loading the icon using the unmanaged (by
>>> any thread pool, but I am not sure about this statement) thread?
>>>
>>> We don’t even have the flag “interrupted”. So technically this icon has to
>>> be loaded.
>>
>> I think it is necessary to save the "interrupted" state in the catch
>> block and try to call waitForID() again. It will be necessary to set
>> "interrupted" flag for the Thread after that(when the waitForID will
>> return without exception).
>>
>>
>>> Sent from myFone
>>>
>>>>> On 21. Jan 2020, at 21:55, Sergey Bylokhov <[email protected]>
>>>>> wrote:
>>>>
>>>> On 1/21/20 12:26 pm, Jason Mehrens wrote:
>>>>> +1 for Sergey suggestion.
>>>>
>>>> Or probably we need to try to load the image again because of the spec of
>>>> the method state this:
>>>> "Loads the image, returning only when the image is loaded."
>>>>
>>>>> ________________________________________
>>>>> From: Sergey Bylokhov <[email protected]>
>>>>> Sent: Sunday, January 19, 2020 9:31 PM
>>>>> To: Volodin, Vladislav; Jason Mehrens
>>>>> Cc: [email protected]
>>>>> Subject: Re: <Swing Dev> Remove System.out.println from
>>>>> ImageIcon.loadImage
>>>>> I guess there are no objections, probably the best way to fix
>>>>> it is to drop the System.out.println and set interrupted flag.
>>>>> On 1/16/20 7:05 am, Volodin, Vladislav wrote:
>>>>>> If people in this distribution list agree, I can start working on a
>>>>>> simple fix and either remove the logging (System.out.println), or
>>>>>> replace it with PlatformLogger. I guess the second solution sounds
>>>>>> better, but I don't know what is the better way to write a test-case for
>>>>>> it.
>>>>> --
>>>>> Best regards, Sergey.
>>>>
>>>>
>>>> --
>>>> Best regards, Sergey.
>>
>>
>> --
>> Best regards, Sergey.