Ymse tanker om dette og hint. Mye om Open Source, noe politikk og annet jeg er opptatt av. Follow the english label for blog posts in English.
2009-03-30
Why adhering to established standards is always a Good Thing
2009-03-21
Her lekker det
| Reaksjoner: |
2009-03-19
The Positive Legacy of C++ and Java
"Java itself will diminish, just as C++ did, to be used in special cases (or perhaps just to support legacy code, since it doesn't have the same connection to hardware as C++ does). But the unintentional benefit, the true accidental brilliance of Java is that it has created a very smooth path for its own replacements, even if Java itself has reached the point where it can no longer evolve. All future languages should learn from this: either create a culture where you can be refactored (as Python and Ruby have done) or allow competitive species to thrive."
2009-03-16
Java Specialist Master Course
Last week I attended Dr. Heinz M. Kabutz' Java Specialist Master Course, which my employer held as an on-site course. These are my field notes from this training.
I strongly recommend this course if you're fluent in Java, but want to take it one step further or remind yourself of some of the advanced features or intricacies.
Day One
Multi-Threading
TreadGroup: Stay away! Not really usable.
A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops, like this one:
synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
}
Day Two
Java IO
Java Input and Output Streams have been designed using Decorator, where additional classes add functionality to underlying streams. Without this we would have extremely many permutations of these classes.
It is only necessary to close() the instance on top of this decorated chain. Closing the input or output stream on a socket will also close the underlying socket.
ObjectOutputStream has two caveats:
- The caching for previously written objects is not bounded, and can result in an OutOfMemoryError
- If you change an object after it has been written, this change will not be picked up and written.
Java NIO
You read or write as much data from / to a channel as you can without blocking. So a thread busy transfering data would spend less time waiting for data. But there is a risk of spin looping if either the source or target is unable to accept data, but isn't closed.Java Memory
Premature tenuring can be a real performance problem. If the survivor spaces are slightly too small, and you hold on to your objects slightly too long, the survivor spaces get contended, and objects get tenured (moved to the old gen tenured space) too soon.
- It takes snapshots. A lot can happen between snapshots.
- It cannot connect to a JVM which is having problems.
Tuning JVM
Don't confuse memory leaks with loitering objects (objects that just stick around longer than necessary).
Recommended heap size: 10% larger than steady state.
Day Three
References
What is the size of a Boolean (64-bit)
- 16 bytes for an object
- 1 byte for the boolean value. This is rounded up to the nearest 8 bytes
- Total: 24 bytes
Object Pooling
Reflection API
Dynamic Proxies
The Method instance is linked to the declaring class (or interface), not to the implementing class or instance. This means this can be passed from the InvocationHandler to the actual implementation you are facading.Data Structures
Sorting
Java uses merge sort because of overall good performance. Quick sort is often faster, but can be much slower in the worst cases, one being if the list is already sorted.
1.4+ HashMap bit masking was originally introduced for performance reasons, but over time the bit mixing has become more complex, thus closing this performance gap. The end result is that the hashing is completely unpredictable and much harder to understand.
equals() should cover all attributes of an object, but hashCode() doesn't need to. Find the attributes that most uniquely identify your instance.
Generics
<N extends Number> means that you now can call methods on Number using N: N n; n.doubleValue();
Generics sometimes produce very confusing compiler errors.
Other Structures
A LinkedHashMap normally orders elements by insertion order, but can also be set up to order elements by access order, placing most accessed elements first. This can be used to create a LRU cache.
Exceptions
RuntimeException's original definition was "exceptions thrown by the Runtime to protect itself from your code."Day Four
Critical Errors Inside the JVM
What to do when the JVM dies:
- Upgrade to a later version of the JRE
- Examine the hs_err file, find out what was causing the problem, and change your code so that it doesn't provoke this behaviour
Best Practices for Exceptions
- Checked vs unchecked
- Custom exceptions -- avoid when possible
- Wrap (chain) low level exceptions
- Don't swallow exceptions!
- Cleanup after an exception -- in the finally block
- Never abuse exceptions for flow control
- Exceptions management strategy is a vital element of code reviews and post mortem analysis
Assertions
Ensure you avoid side-effects : assertions could always be disabled, effectively disabling this statement.
You could assert that you hold the lock as expected: assert Thread.currentThread().holdsLock(lock)
When using assertions, the entire system must be tested both with assertions enabled and disabled.
Useful to verify preconditions, postconditions, and class invariants.
Java Optimizations
Order of importance for performance improvements:
- Design and architecture
- Algorithm selection
- Code implementation
- System configuration
- System infrastructure
- Start by looking at hardware -- CPU, memory usage, I/O. Locate any bottlenecks on the hw level. Most performance problems appear as CPU bottlenecks.
- Then look at JVM level: threads, memory usage, garbage collection.
- Application level: Basically lock contention.
- People level: study usage pattern, arrival rates.
The HotSpot compiler
Problem Areas
The two major problem areas are excessive looping and excessive object creation.
Special byte codes to handle the first four arguments and local variables. Long and double counts as two. Move most-used variables into these slots.
Object Pooling usable only for expensive resources (files, sockets, connections, threads)
You don't save memory by using substring(), since this new String instance would share the char[]. You'd need to create a new String.
Profiling Tools
hprof is bundled with the JVM. Can do cpu and heap profaling. Its output can be read by many tools.Logging
Don't write your own logging framework....
Mentions Commons Logging, but fails to mention that Commons Logging is hated by many developers: http://www.qos.ch/logging/thinkAgain.jsp. Also it is claimed to have memory leaks: http://www.szegedi.org/articles/memleak.html
Also describes setting up logger statically per class, with some tricks involving a stack trace to get the class name. It is probably better to have a transient instance field.
SLF4J is also a wrapper API, enabling you to select logging implementation at runtime through the classpath. But SLF4J is more modern.
