How to reduce PDF file size on Macs and Linux?

 Of the suggestions I saw, using the "shrink PDF" script files with Ghostscript was the best.

Install Ghostscript first.  On Linux, apt install ghostscript or on Macs using homebrew, brew install ghostscript.

Save that shrink PDF script into a shrinkpdf.sh file.  Make sure to chmod u+x shrinkpdf.sh to allow it to execute.

Then use it, /path/to/shrinkpdf.sh in.pdf out.pdf.

On my old Mac running Sierra macOS 10.12, Ghostscript had trouble running because the way brew built it, Ghostscript was looking for the libXt.6.dylib library in the wrong place.

You need XQuartz installed first.  But XQuartz installs X11 libraries into /opt/X11.  But Ghostscript looks for X11 libraries in /usr/X11.

Easy fix?  Symlink the X11 directory to where Ghostscript expects it.

Go to where Ghostscript looks for X11: cd /usr

Then symlink to where the X11 libraries actually are: sudo ln -s /opt/X11.



Why upgrade past Java 8?

What reasons are there to use Java versions newer than Java 8 (JDK 1.8)?

I'll give two: (1) security, and (2) great new features!  Let me explain.

(1) security

The last "major release" of Java was Java 9.  The Java upgrade cadence changed at that point.  They're now on a steady stream of "feature releases" model.  Kind of like how there's no major release of Chrome, Firefox, or Windows 10 nowadays... it's just a stream of feature releases.  Java's cadence is 6 months, so about every 6 months, they ship and bump the version number.  JDK 15 was released not long ago.

So who cares?  Well only the current release (JDK15 as of this writing) gets proper maintenance and security updates for free.

Note "for free".  Certainly some software development shops will stick with old JDKs, but they might have good reasons and good mitigation for using old JDKs.  Good reasons like certain customers are stuck (for whatever reason) with old JDKs, or vendors of certain dependencies they need are stuck with old JDKs.

Good mitigations include... paying for paid Long Term Support versions of Java from a JDK vendor.  E.g. it looks like Azul offers a JDK 8 LTS, although the current LTS from any vendor is JDK 11.  The next LTS is JDK 17 scheduled for September 2021 (because of the stream of feature releases model, JDK 12 thru 16 are relatively small feature upgrades, hence the gap between the LTS versions).

You can even use the "free LTS" versions if you want to download those binaries from Oracle, Red hat, or Azul etc., just don't expect actual support without paying!  Mostly they backport security fixes from current version to the latest LTS version, and provide real support for paying JDK LTS customers.  So "free LTS" builds aren't really fully supported for free.  If you must use an LTS release, at least use the latest one (that's JDK 11).

But really, for free security and maintenance, you should just use the latest version.  It's no different from Chrome or Firefox... you should always use the latest to avoid security vulnerabilities.

As for which vendor to choose from? There's Oracle, Red hat, Azul, Amazon Corretto, AdoptOpenJDK, etc.  But they're all built from the same OpenJDK from Oracle, even Oracle's JDK, and they contribute back upstream to OpenJDK.  If you want a slick downloads page and easy installers, AdoptOpenJDK and Azul looks pretty ok.

(2) great new features

Java has a lot of great features in newer releases.  These features aren't just for looks, they bring life back into Java.  I know... "kids these days"... always wanting

  • type inference --- like in Swift, C#, etc
  • lambdas --- like in lisp, C++11, JavaScript, etc.
  • async --- like in JavaScript, rust, etc
  • better garbage collectors --- like Go

But those language features are, rightly or wrongly, table stakes to be considered an up-to-date language nowadays.  Even modern C++ has type inference and async, and smart pointers with garbage collection (reference counted).


  • Java 8 has lambdas
  • Java 10 has type inference (use var)
  • I believe Java 16 will have virtual threads (Java's better answer to async) from Project Loom
  • Java 15 has better garbage collectors (by some metrics), and in fact multiple GCs to choose from for different use-cases: Shenandoah, ZGC, and G1 (admittedly, only more advanced development might care about GC performance)
  • There's multiline text blocks since Java 15, finally
  • There's extended switch expressions that can yield values since Java 14
  • and also a safer switch statement/expression using "arrow case" labels instead of "colon case" labels since Java 14
  • Java 9 introduced JShell, which is fantastic to be able to use a REPL to test out Java code

There's so much to get excited about!  There's a joke about Java being the new Cobol.  But not anymore with features that bring it parity with other languages.