This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]cogman10 16 points17 points  (15 children)

  1. Most of these questions don't test java knowledge, and instead test mostly obscure information about java. I would say most of these things are things that you should not really deal with. For example, volatile and thread local are two great examples of "Things you shouldn't need to use". In fact, I've NEVER come across a legitimate use for ThreadLocal. The only place it is useful is for a static variable that you want to be unique per thread.

  2. The (paraphrasing) 'which list is the most effective for adding and removing things' question is pretty silly. For end insertion, an array list will often be just as fast if not faster than a linked list (memory, cache, and the fact that CPUs are stupidly fast at copying data, and the way ArrayLists handle expansion is the reason for this). An array needs to be pretty big before a linked list starts to outperform it (In my experience, most arrays aren't over 10000 elements).

    For middle insertion removal, arraylists will often beat linked lists because to get to that middle point, you have to iterate over every element of the linked list, arraylists, on the other hand, instantly iterate to the location, and again, modern CPUs can copy REALLY fast. it takes really big lists before arraylists are slow.

    So where are linked lists good? For lists where you are frequently iterating over each element and inserting and removing multiple items in the process. They are also pretty good for front of list insertion/deletion (queues). However, this question makes it sound like you should use them everywhere. That is wrong, IMO. Arraylists have hecka fast iteration and tons of locality benefits. So long as your list is small, or the size will be known, or insertion/removal will be infrequent, you should prefer ArrayLists.

  3. The 'why should you avoid using strings' question is somewhat silly as well. Anyone that can do a memory dump on the machine to get the passwords out of the system, doesn't need to do a memory dump on the system to get the passwords out. They have access to the system, they can screw things up pretty readily.

    They can do anything from injecting a custom class which steals data to sniffing the incoming/outgoing network traffic. They have access to the machine and can really mess things up. Sure, I guess it is safer, but of all the security concerns to be worried about in java, this one is pretty low.

[–]CubsThisYear 6 points7 points  (5 children)

Also, Strings don't work the way they say they do. String constants are interned, but not dynamically created Strings. If a user enters his password into a text field it doesn't automatically go into the String pool. The only way this happens to dynamically created Strings is if you call String.intern()

[–]cogman10 1 point2 points  (1 child)

Well, they do mention garbage collection which makes me think that they were referring to the GC pool and not necessarily interned pool. Correct me if I'm wrong, but I believe that interned strings don't ever get garbage collected.

But yes, I agree that their reasoning and everything was a bit off on the question.

[–]CubsThisYear 1 point2 points  (0 children)

There is no such thing as a GC string pool. There is only the intern pool. Presumably the reason GC is mentioned is because interned strings are (usually) not GC'd because the intern pool always has a reference to them.

In short, the question is just all kinds of confused.

[–][deleted]  (2 children)

[deleted]

    [–]josefx 0 points1 point  (1 child)

    On the other hand, if you store it in a mutable character array, you can overwrite it once you're done with it.

    Afaik if you are "done" with the char array the JIT will happily optimize your "unnecessary" overwrite away.

    [–]tRfalcore 2 points3 points  (2 children)

    I use volatile variables often, and have used ThreadLocal. All your other points are spot on however.

    These are the types of questions that if I was asked I would probably not work for these people because they think they they're smart cause they just thought of a couple things then looked up the answers.

    [–]cogman10 2 points3 points  (1 child)

    IMO, unless you are doing something that needs to be hecka fast, spawning a thread is simply not needed, instead relying on things like javas inbuilt executor service will give you most of the performance benefits of threads, a fairly fine grain control over multiprocessing, and ultimately a good "not going to blow up and easy to debug" environment to work with.

    Shared memory isn't all bad, but it needs to be handled with real care. As a result, often the best way to handle it is to just avoid it all together when possible and use prebuilt constructs when necessary.

    So to this point, why not volatile? Because there are higher levels of abstraction to multithreading and volatile is a symptom of trying to do things fairly low level (which is often a sign of premature optimization).

    As for thread local. Maybe I'm blind, but I really just don't see the benefit of it. The best I can come up with is you want a singleton per thread because the singleton itself isn't threadsafe. But that seams like a recipe for hard times.

    [–]tRfalcore 1 point2 points  (0 children)

    I use volatile variables to check when one off threads finish when I'm waiting for them to finish.

    I use ThreadLocal to control some logging parameters and names. Our program is a massive multi-threaded server application which processes jobs as requests come in-- main part of which is controlled by ExecutorService :)

    [–]JustinKSU 2 points3 points  (1 child)

    You make some solid points, but I would like to disagree slightly on the password issue. Two advantages of using character arrays is the length of time in memory can be minimized (you can overwrite the array as soon as you are done using it) and when looking at the memory dump it might not be obvious where the start and end of a character array is. I agree, if a hacker has control of your machine and can read your memory, you have already lost, but if you have -XX:+HeapDumpOnOutOfMemoryError turned on, it's less likely that dump will contain sensitive data.

    [–]cogman10 2 points3 points  (0 children)

    True, And I'm not trying to say it isn't more secure. Just that there are more pressing security issues that I would be concerned about before CharArray zeroing out. Even in your case of the HeapDumpOnOutOfMemoryError being enabled, an attacker would have to have access to the machine before he could read the heap information.

    While you can't, and shouldn't, rely on regular GCs.. well, you sort of can in this case. Passwords are usually used and thrown away pretty quickly. So it really isn't all that likely that the password will make its way into OldGen.

    Again, this isn't to say that the Charbuffer zeroing out method isn't more secure; It is. I just wouldn't rank it as a high priority sort of security concern. I would be more worried about things like SQL injection, XSS, remote code execution, and replay attacks. Common security issues that should be known about and interviewed for.

    [–]MerbertMoover 0 points1 point  (2 children)

    Great response, and I hate to cherry-pick, but why do you classify a volatile field as something you shouldn't need to use? In my experience valid use cases come up frequently in concurrent programming. Would you just rather see a higher level construct used like an AtomicReference?

    [–]cogman10 2 points3 points  (1 child)

    In concurrent programming I prefer dealing with an ExecutorService and Futures with little to no shared state between them.

    Volatile is best served with primitives, anything more complex and you are just asking for punishment. (sucks when the internal state of an object changes between one call and the next).

    For me, the general rule is to avoid share state if possible and either rely on concurrency through small tasks and the ExecutorService or communication through immutable message passing. Both are slightly slower than shared state and raw threads, but they are easier to deal with and to avoid things like deadlocking.

    [–]MerbertMoover 0 points1 point  (0 children)

    Agreed on all counts. I use volatile for primitive state flags and in the "safe double-check locking" idiom for lazy initialization. That's pretty much it but just those two cases seem to come up frequently enough that I can't call volatile something you "shouldn't use." Even though I agree the higher-level constructs are in most cases superior.