Originally taken from http://www.panix.com/userdirs/jdw/javasucks.html. Thanks to one of the guys in #PHP for the link
If Java had proper garbage collection, most programs would self-delete upon execution. -- Jucius Maximus

FOREWORD: Just because this page is about Java and mentions a bunch of Java-related problems does not mean it will help you to solve them. If you're looking for actual, immediate answers for why you're getting "ocijdbc8 unsatisfied link error", you'll have to look elsewhere. Sorry.

Why Java Sucks For Sysadmins

I am not a fan of Java. (The programming language, not the drink (which I love) or the place.) There are a lot of pages out there on how and why Java sucks, but most of them are written by and for programmers, e.g. "Java sucks because you can only singly inherit dynamic classless initialization methods!" (Um...yeah! Righteous! Preach it, brother!) I'm sure they're all valid enough, but Java doesn't just suck for programmers, it sucks for sysadmins too! There's enough suckiness in it for everybody!
I should really specify more carefully exactly what I mean by Java (since this is something even its supporters have to do). I learned a little of Java the language proper back when it was new and the hot thing to learn: it seems like a language like any other, no better or worse than many others. Fussy with the syntax and rather verbose, but that could be said of other languages too. As a sysadmin, I don't have to deal much with it anyway. Java the VM and class library is a different issue. That I do have to deal with. Then there's the whole culture surrounding Java...and that's a whole other can of worms.

That said, the major points against it from this sysadmin's point of view are:

  1. It is slow. Compared to compiled C programs, Java loses every time. Try time tar xf nonexistentfile and time jar xf nonexistentfile. On an otherwise idle 440MHz UltraSparcII running Solaris 8 with the Java 2 JRE 1.3.1, it takes jar over half a second just to report that it can't find the file! tar, on the other hand, takes just over 1/100th second. The fact that it's a semi-interpreted language is not an excuse. If I need to pull a plow, and you send me aardvarks instead of draft horses, saying "Well, they're aardvarks and you just have to expect that from aardvarks" does not get my field plowed any faster. So what's half a second, anyway? Well, times several million hits on your website per day, it's a whole lot. But, you say, it depends so much on your JRE! So, say I, show me any JRE as fast as native code. And if Sun, the inventor of Java, can't manage to make a decently fast JRE, it doesn't inspire great confidence, does it? Even if there are great JREs out there, the fact that one has to go hunt them down to get decent performance is a strike against Java. C programs pretty much work or they don't.
    I keep hearing "Well, the next generation of JREs will be just as fast as native code - maybe even faster!" I'll believe that when I see it. I've been hearing it since the first days of Java.
  2. It manages to be both verbose and unhelpful at the same time. Let's continue to use tar/jar as our examples.
    devweb02:~$ tar xf qwertyuiop
    tar: qwertyuiop: No such file or directory
    devweb02:~$ jar xf asdfghjkl
    java.io.FileNotFoundException: asdfghjkl (No such file or directory)
            at java.io.FileInputStream.open(Native Method)
            at java.io.FileInputStream.(FileInputStream.java:64)
            at sun.tools.jar.Main.run(Main.java:186)
            at sun.tools.jar.Main.main(Main.java:904)
    
    One of these error messages is helpful. One is not. (Not even "jar: FileNotFoundException". But "java.io.FileNotFoundException". Sure hope you didn't have more than one java process running at once.) And the situation only gets worse when you're dealing with larger projects. When a program runs into a problem, a concise description, like "Cannot open connection to host.example.net", is useful. A 100-line stack dump is not. (The beautiful thing about programs in C is that you can easily get a stack dump if you want it -
    devweb05:~$ pstack $$
    5454:   -bash
     ff19bcf0 waitid   (7, 0, ffbefa30, 7)
     ff1560c0 _waitpid (7, ffbefb24, 4, ffbefb24, 21638, 39994) + 60
     00039994 ???????? (8ccfc, 8c7b4, 38708, 2, 1, 1)
     00038b00 wait_for (a8950, 16d6, 0, a7510, 0, 0) + 120
     0002cc88 execute_command_internal (8cc00, 0, ffffffff, 0, 0, 0) + 740
     0002c308 execute_command (a8890, a8890, 0, 0, 0, 0) + 44
     00021970 reader_loop (8c400, 8c400, 0, 1, 1, 1) + 1dc
     0001fc08 main     (8c400, 1, 8cc00, 8c400, 0, 0) + 890
     0001f360 _start   (0, 0, 0, 0, 0, 0) + b8
    
    - but you don't get it unless you want it. You can use a debugger on a core file or running process if your platform doesn't have pstack or the like.) The general problem is that Java gives you messages which are meaningful in a Java context and not in a system context. I suspect this is because Java was written in a sort of bubble-boy environment, where it had very little to do with the real world (cf. Perl) and it persists because most major Java apps are written by people who are in love with Java, and they are in love with Java because they are programmers; language-related messages are the only things that mean anything to them. Here's a real example:
    **** Error      Fri Aug 31 16:04:18 EDT 2001    999288258613    /       a__.n______.N______Resources->cantResolveComponent : Unable to resolve component /a__/d_____/service/jdbc/JTDataSource  java.lang.UnsatisfiedLinkError: no ocijdbc8 in java.library.path
    **** Error      Fri Aug 31 16:04:18 EDT 2001    999288258613    /               at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1312)
    **** Error      Fri Aug 31 16:04:18 EDT 2001    999288258613    /               at java.lang.Runtime.loadLibrary0(Runtime.java:749)
    **** Error      Fri Aug 31 16:04:18 EDT 2001    999288258613    /               at java.lang.System.loadLibrary(System.java:820)
    **** Error      Fri Aug 31 16:04:18 EDT 2001    999288258613    /               at oracle.jdbc.oci8.OCIDBAccess.logon(OCIDBAccess.java)
    **** Error      Fri Aug 31 16:04:18 EDT 2001    999288258613    /               at oracle.jdbc.driver.OracleConnection.(OracleConnection.java)
    **** Error      Fri Aug 31 16:04:18 EDT 2001    999288258613    /               at oracle.jdbc.driver.OracleDriver.getConnectionInstance(OracleDriver.java)
    **** Error      Fri Aug 31 16:04:18 EDT 2001    999288258613    /               at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java)
    **** Error      Fri Aug 31 16:04:18 EDT 2001    999288258613    /               at java.sql.DriverManager.getConnection(DriverManager.java:517)
    **** Error      Fri Aug 31 16:04:18 EDT 2001    999288258613    /               at java.sql.DriverManager.getConnection(DriverManager.java:146)
    **** Error      Fri Aug 31 16:04:18 EDT 2001    999288258613    /       ....stack trace CROPPED after 10 lines.
    
    Only the first line is relevant to the system administrator, and that only tangentially. In fact, the system tacitly acknowledges the uselessness of the flood of error messages by stopping them after a point.

    Here's another real example:

    ***ERROR***:    Wed Apr 10 15:52:27 EDT 2002    1018468347628
    /a__/d_____/servlet/pagecompile/PageCompileServlet
    The detailed exception is: java.io.IOException: Not enough space
    
    That's the "detailed exception"?! "Not enough space"? Not enough what space? Heap? Disk? If that's the detailed one, I don't want to see the short version. (I'm picturing Java just saying "No." and dying.)

  3. It is fragile, and in some parts, actually broken. Far too many times have I heard "Oh, you need to use jre 1.1.8, not 1.1.7", or "This needs green_threads, not native_threads." I can't claim that non-java programs never have library problems, but they are far less common than Java's ticklish dependencies. It should be considered a sign of how finicky it is that even Sun's jar (just to pick on poor beleaguered jar one more time) requires an 87-line wrapper script to make sure it can run correctly. To name one particular broken part, the AWT (Abstract Windowing Toolkit) did not work well with the X Windowing System. Try to run a graphical java application with the output exported to another display, and while the window would come up, most of the widgets in it would be broken - not working correctly or not appearing at all. "The network is the computer", huh, Sun? (Apparently the AWT has been scrapped now, but its replacement, Swing, does not work much better.) The comments I made about the JRE apply here, too. I want programs to work without having to hunt down some unknown number of other components in order to get acceptable performance out of them.
  4. It's unfriendly to much of a sysadmin's standard bag of tricks for testing and troubleshooting. Ever truss a java process?
    yoyodyne:~$ truss 2>&1 java HelloWorld >/dev/null | wc -l
        1107
    
    One thousand one hundred seven lines of truss output just to run Hello World?
    yoyodyne:~$ truss 2>&1 java HelloWorld >/dev/null | egrep -c "sema|mutex"
    40
    
    Forty lines of semaphore or mutex activity to run Hello World?
    a) No wonder it's slow,
    b) Good luck finding the meaningful needle in the haystack of syscalls.

    yoyodyne:~$ ldd HelloWorld.class
    ldd: HelloWorld.class: unsupported or unknown file type
    
    Oops, can't look at the dependencies either. I've never tried using a library interposer with a Java program, but I don't think it would be much fun.

Other failings of Java are not intrinsic to the environment, but of the way it's been marketed, and why people say everyone should love Java.

  1. "It's object-oriented!" As a sysadmin, I don't care. Not one whit. I notice that the human race miraculously managed to survive many years of non-object-oriented programming, somehow.
  2. "It's cross-platform!" This is maybe an advantage for programmers. Not for sysadmins. Needing to run the same application - to say nothing of the same binary! - on multiple platforms is not that common. (Some companies apparently like it because they can develop on Windows desktops and deploy on Unix servers. I have seen exactly how well this usually works.) The particularly cynical part of me wants to say, "So it can be broken on multiple platforms at once!" but unfortunately there's a lot of truth to that. I'm sure "write once, run anywhere" really does look appealing to software companies. One app that will run on Solaris, Windows, HP-UX, Irix, and AIX? Great! Right? Unfortunately for the consumer, though, the software companies are not about to quintuple their testing and debugging efforts. (That would probably erase most of the gains of "write once, run anywhere", frankly.) So the consumer gets an app that hasn't been effectively tested or debugged on his platform. And do you really think that the software companies are going to start hiring five times as many support staff, or support staff skilled in five times as many operating systems?
    Furthermore, properly written C is pretty cross-platform too. Or maybe I just hallucinated the Apache project and NetBSD. Badly written Java isn't cross-platform either - I've actually seen vendor code that has nonportable stuff like FileInputStream("C:\GronkSoft\Appulator\Store\Config\Flargulator.properties") embedded in it. This is obviously a development problem, not strictly a language problem, but the point is that cross-platform-ness is a state of mind, not just a platform.
  3. "It's easy to code in and reduces development time!" Things that make it easier to do your job are good, but not if they come at the cost of the quality of the result. As I said before, I'm not a programmer, but I strongly suspect that management and skills are a much greater factor in determining the speed and quality of a project than the particular language you use. That's certainly the way it is in system administration. It has been pointed out that good software takes time, anyway. Changing the language you use just to speed up one particular part of the project seems like rather a bold (read "poorly thought-out") move to make. And for your sanity and mine, I won't refer you to the web pages out there that basically say "I like Java because it lets me program without being a good programmer!" Bleurgh.

Miscellanea:

  1. "What about Perl, huh? Doesn't Perl have all the same problems, wise guy?" Well, yes and no. Perl is no speed demon, being an interpreted language, but OTOH it's never been sold as a replacement for C, either. And in my experience, it still manages to be faster in execution than Java, though that's not very scientific evidence. You do run into twisty mazes of dependencies from time to time, but I've always found them easier to deal with than Java's, and its error messages are far better than Java's:
    sadalsuud:~$ perl perlopen.pl
    Can't open file: No such file or directory at perlopen.pl line 1.
    
    and
    sadalsuud:~$ perl perlinc.pl
    Can't locate NONEXISTENT.pm in @INC (@INC contains: /usr/lib/perl5/i386-linux /usr/lib/perl5 /usr/lib/perl5/site_perl/i386-linux /usr/lib/perl5/site_perl /usr/lib/perl5/site_perl .) at perlinc.pl line 1.
    BEGIN failed--compilation aborted at perlinc.pl line 1.
    
    Perl is also open-source, so you can actually fix the broken stuff vendors send you, as opposed to waiting around for them to fix their bytecode. (I have run into intentionally obfuscated Perl that is effectively impossible to read; I can't excuse this and won't use it if I have a choice.)
  2. Sun won't eat its own dog food. NEW!
    If Java's so great, how come none of Sun's major software (to the best of my knowledge) is written in it? If it's not right for any of their projects, why is it right for any of ours?
    Well, this is not quite true any more. A reader informs me that the Sun Management Center, the ODS GUI, parts of Star Office, and other system configuration tools are now written in Java. Given that Star Office is supposed to run just about everywhere, I'm not too surprised at that one. Given that ODS is strictly a Solaris tool, I am a bit surprised at that one, but the old ODS GUI was so bad it seriously needed to be taken behind the barn and shot, and probably when the time came to do a new one, there was a management fiat to do it in Java. The reader informs me that the process of rewriting is going slowly and not producing terribly satisfactory results. Quelle surprise, eh?
  3. Java breaks OS standards. The way you have to invoke Java class files grossly violates long-accepted standards on Unix (I don't know about Windows). For example:
    devweb02:~$ java HelloWorld.class
    Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld/class
    devweb02:~$ java HelloWorld
    Hello World