Why Java Sucks for Sysadmins

Why Java Sucks For Sysadmins Originally taken from http://www.panix.com/userdirs/jdw/javasucks.html. This is mirrored here so it can live on forever. Java 1.x... never forget.
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:
    a__.n______.N______Resources->cantResolveComponent : Unable to resolve component /a__/d_____/service/jdbc/JTDataSource  java.lang.UnsatisfiedLinkError: no ocijdbc8 in java.library.path
            at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1312)
            at java.lang.Runtime.loadLibrary0(Runtime.java:749)
            at java.lang.System.loadLibrary(System.java:820)
            at oracle.jdbc.oci8.OCIDBAccess.logon(OCIDBAccess.java)
            at oracle.jdbc.driver.OracleConnection.(OracleConnection.java)
            at oracle.jdbc.driver.OracleDriver.getConnectionInstance(OracleDriver.java)
            at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java)
            at java.sql.DriverManager.getConnection(DriverManager.java:517)
            at java.sql.DriverManager.getConnection(DriverManager.java:146)
    ....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
    
    • It's confusing. The file is named HelloWorld.class, but you can't call it that.
    • As is usual for Java, the error message gives you no clue what might be wrong, unless you're already familiar with what you have to do.
    • It's extremely un-Unixy. Unix programs traditionally don't give a flying leap what they're called (with a very few notable exceptions). perl script.pl works, but so does perl Ekki-Ekki-Ekki-Ekki-PTANG if you happen to name your script that. If I rename bash to mash, it still works just fine. ("rbash" is one of the notable exceptions. It still works, it just works differently.) The fact that people familiar with Unix, working for a major Unix vendor, would create a language like this is mindboggling.

      Here's another stunning example of the poor integration of Java (with Solaris, anyway).

      yoyodyne:~$ pwd
      /export/home/jdweiner
      yoyodyne:~$ java HelloWorld
      Hello World
      yoyodyne:~$ cd ..
      yoyodyne:/export/home$ java jdweiner/HelloWorld
      Exception in thread "main" java.lang.NoClassDefFoundError: jdweiner/HelloWorld (wrong name: HelloWorld)
      
      This is jaw-droppingly braindamaged from a Unix POV. You actually aren't allowed to address the class file by its location in the filesystem! This shouldn't be surprising, given the fact that you aren't allowed to address it by its actual filename. I'd be curious to know how Java developers deal with this. It's normal to be able to rename myprogram to myprogram.old if you want to compile a new version of myprogram, and then still be able to invoke myprogram.old. But, of course, you can't do that with java. You can do this:
      panix2:~$ env CLASSPATH=~/myjavaprogs java HelloWorld
      
      but that doesn't help if you've renamed the file. It's painfully clear that Java did not begin its life in the Unix world, and simply got bolted on like a sidecar when Sun decided that it would be a nifty tool. To which they basically admit in http://java.sun.com/features/1998/05/birthday.html:
      Java technology was created as a programming tool in a small, closed-door project...[for] the convergence of digitally controlled consumer devices and computers.

      In the summer of 1992, they emerged with a working demo, an interactive, handheld home-entertainment device controller with an animated touchscreen user interface.

      ...says James Gosling. "We were pitching the cable companies on the idea that this is what your network should look like. It was interactive, and users could read and write information into the system. But the companies didn't want to lose that much control." It was too far ahead of its time, and the team, now numbering 70 people, was still searching for a target market.

      "After we realized that there wasn't a business in digital cable television, we had a group meeting at The Inn at Squaw Creek near Lake Tahoe. We had to figure out what to do with this technology, or what to do with our lives." There, over the course of three days, John Gage, James Gosling, Bill Joy, Patrick Naughton, Wayne Rosing, and Eric Schmidt had a group epiphany: why not the Internet?"

      The article goes on to explain that Java was, in fact, originally intended only for things like interactive web pages. At what point they decided an environment so closely tied to interactive TV and web page animations would be appropriate for general-purpose computing is never explained.

      Another telling quote, this time from http://www.wired.com/wired/archive/3.12/java.saga.html :

      In April 1991, the team moved from Sun's main campus to office space above a branch of the Bank of America on Menlo Park's Sand Hill Road, cutting itself off from Sun's internal computer network. The programmers disconnected culturally as well. ''We thought if we stayed over there, we would end up with just another workstation,'' Sheridan says. "I was obnoxious about keeping it secret.''
      I.e., "we threw out all the existing standards and then expected everybody to change to do things our way."