2

I'm writing a REST client and it has an access token with a fixed expiration time.

How do I ensure that a new token is requested before the expiration time? I see two options:

  1. Timer
  2. Some shenanigans with the finalize method possibly using the ref package

1) would require me to create a new thread that would run in a given time and request a new token. It seems wasteful to me.

2) would take advantage of the GC thread which will run anyways, so I would not need to create a new thread. When finalize runs just check if the token is about to expire, if yes request a new one, if not make the object available again until the next GC cycle runs.

Comments or other ideas?

Roland
  • 7,525
  • 13
  • 61
  • 124
  • 4
    `GC thread which will run anyways`. This might not be true all the time. GC is run by the JVM only if it needs to be run. If your application has enough memory available, GC might not be triggered at all. So, I would suggest not to rely on this approach. – anacron Feb 10 '17 at 06:31
  • Whenever I have two options and the other one is "Some shenanigans" I always go for that. Makes the code more interesting⸮ – Kayaman Feb 10 '17 at 06:39
  • That's what the [⸮](https://en.wikipedia.org/wiki/Irony_punctuation) was for :) – Kayaman Feb 10 '17 at 06:45
  • You need to join the Unicode revolution. – Kayaman Feb 10 '17 at 06:51
  • 2
    Still premature optimization or in this case premature cleverness is not a good idea. Just because something *seems* wasteful, is not a good indication of whether it's a good idea or not. If you're creating 1 timer you don't even need to think about it. If you had 1000 of them and they were causing performance harm, then you'd need to consider alternatives. And even then you would be wise to stick to tried and tested solutions, instead of rolling your own by abusing GC functionality. – Kayaman Feb 10 '17 at 06:54
  • 1
    DO NOT USE FINALIZE! It is a subtle beast with dire side effects that has particular use cases and needs. One does not simply manage resources with a finalizer. – Lew Bloch Feb 10 '17 at 07:03
  • 1
    You can't rely on `finalize()` for *anything*, let alone a time-dependent action. It may never run at all. – user207421 Feb 10 '17 at 09:36

1 Answers1

1

Off the top of my head, problems that can arise by using finalize:

  • Debug hell. You depend on GC invoking your method, you don't have a proper reference to the object, etc. etc. etc.
  • Increased chance of not cleaning up properly, since you are using finalize() to create resources and open new connections, instead of closing and cleaning them up.
  • GC might never be called and the token is never renewed.
  • An exception can occur while getting the new token, so now you're throwing unexpected exceptions in the GC thread -- do not want.
  • Getting the new token succeeds, but takes a long time for whatever reason (e.g. a slow network), so you might get a java.lang.OutOfMemoryError: GC overhead limit exceeded.

Creating a new thread is relatively inexpensive. Sure, there are better methods, but we are talking microseconds here. You say that creating a new thread "seems wasteful" but, just by thinking about alternatives to it, you already wasted more time than the overhead caused by creating a new thread every second for the next 40 years.

Use a timer.

EDIT: or, better yet, use ScheduledExecutorService (see comments).

Community
  • 1
  • 1
walen
  • 7,103
  • 2
  • 37
  • 58
  • You might want to add that OP should consider using a `ScheduledExecutorService` for its comparative advantages for this particular use case (i.e. exceptions occurring from request) - http://stackoverflow.com/a/409993/3308999 –  Feb 10 '17 at 15:12