2

During a code review, I got into a discussion about the following method:

private String getAccessToken(HttpServletRequest request) {
    Enumeration<String> authHeaders = request.getHeaders("Authorization");

    for (; authHeaders.hasMoreElements(); ) {
        String header = authHeaders.nextElement();
        if (header.startsWith(BEARER_PREFIX)) {
            return header.substring(BEARER_PREFIX.length());
        }
    }
    return null;
}

One suggestion was that it would be better from a performance point of view to do this:

String header;
for (; authHeaders.hasMoreElements(); ) {
    header = authHeaders.nextElement();
    //...
}

in order to avoid allocating the header many times. As a C++ programmer, this surprised me. My assumption would be that the function was doing something like this:

for (; authHeaders.hasMoreElements(); ) {
    char* header = authHeaders.nextElement();
    //...
}

I.e. header is a stack variable that points to something on the heap and that no allocation would need to be done. But I must admit that I know C/C++ better than I do Java, especially when it comes to what guarantees the language makes about when allocation occurs.

Does moving the declaration of the string variable outside of the loop matter one way or the other?

6
  • 2
    Why don't you compile the both and see if there is any difference in the bytecode? Commented Apr 28, 2015 at 9:16
  • 2
    I addition, the JIT compiler will probably change the generated bytecode if it is necessary. Commented Apr 28, 2015 at 9:16
  • 5
    Also, this micro-optimization is pointless and is harmful since it makes the code less readable, unless your profiler said this is indeed a problem - don't do these optimizations, remember that redability is for programmers, micro optimizations is for compilers Commented Apr 28, 2015 at 9:17
  • I'm more worried about making sure my mental modal of how Java code executes is correct, rather than this specific case. So far it's "primitives the values of references are sort of stack variables, everything is goes on the heap and allocated with a garbage collected equivalent of malloc". Commented Apr 28, 2015 at 9:19
  • I completely agree with amit: whoever derailed your review to focus on such questions is not doing you a favor. He is wasting his and your time with absolutely pointless discussions! Please note: of course it is good to understand the semantics of all language constructs. But the intention is about understanding; it shouldn't be about "optimizing". Commented Apr 28, 2015 at 9:31

3 Answers 3

2

If you are unsure how the REFERENCE with name "header" is allocated then:

According to JVM specification at: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.6

2.6. Frames

A frame is used to store data and partial results, as well as to perform dynamic linking, return values for methods, and dispatch exceptions.

A new frame is created each time a method is invoked. A frame is destroyed when its method invocation completes, whether that completion is normal or abrupt (it throws an uncaught exception). Frames are allocated from the Java Virtual Machine stack (§2.5.2) of the thread creating the frame. Each frame has its own array of local variables (§2.6.1), its own operand stack (§2.6.2), and a reference to the run-time constant pool (§2.5.5) of the class of the current method.

2.6.1. Local Variables

Each frame (§2.6) contains an array of variables known as its local variables. The length of the local variable array of a frame is determined at compile-time and supplied in the binary representation of a class or interface along with the code for the method associated with the frame (§4.7.3).

So it does not matter where the header reference is declared - the byte code contain information about it and space for it in the stack will be allocated only once.

Placing the variable outside of the loop is not needed and is a bad coding practice since its visibility scope is bigger than needed.

Sign up to request clarification or add additional context in comments.

Comments

2

There is no difference as the allocation of the object is done in authHeaders.nextElement().

So the object will be created - no matter where the variable is declared.

After that the garbage collector will remove the now unused object, no matter how the variable is declared.

Comments

0

When you say String header = authHeaders.nextElement(); you are refering to a new location every time which is being referenced by name header.

Moving the declaration of a variable out of the loop implies you are using the same memory location instead of using multiple memory locations and leaving it to the garbage collector to remove them. This helps a lot when you are dealing with huge datasets.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.