Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

2021-01-12

My app uses only java.base, but actually jdeps missed the jdk.crypto.cryptoki module!

I was building a small app and I purposely used only the java.base module.  That way when I build a custom Java Runtime for it, I can build the smallest possible runtime with jlink.

Java's jdeps lets you know which module your app depends on, and it said my app only uses the java.base module. 

Build the runtime with jlink and run my app with it and oops, an error having to do with cryptoki.

Turns out jdeps made a mistake and did not identify the jdk.crypto.cryptoki module!

I suspect my use of the java.net.URI class was to blame, as it was used to access an https URL.

Anyway, if you purposely depend only on the java.base module, but also use the URI class, note that it may actually also depend on the jdk.crypto.cryptoki module!


2021-01-06

Build your own custom Java Runtime with jlink and jdeps

Since Java 9, the way Java programs are supposed to be distributed changed.

It used to be that users would install a Java Runtime Environment (JRE) on their system.  The user then gets the Java app from the app developer.  The Java app then runs on the JRE that's installed.

Some OS like Macs used to even have a "system" JRE installed as part of the OS.

The world's moved on from that style of app distribution.  Nowadays, many users want statically compiled programs, or a single executable file with no dependencies.  For better or worse.

That means when you develop a Java app and want to distribute it, it's on you as the developer to create your own custom Java Runtime and package that runtime together with the rest of your app for distribution.

The upshot is that if you don't use too much of the Java standard library and customize your Java Runtime, then you pay for only what you use in terms of the size of the Java runtime you need to package with your app.

You can find what Java modules your app depends on using jdeps easily: jdeps my.jar

Then you can use jlink to create the Java Runtime your app needs: jlink --output my-custom-runtime --add-modules java.base,and.other.modules

Then you can run your app with the custom Java Runtime: /path/to/my-custom-runtime/bin/java -jar my.jar

The Java Runtime that jlink creates is specific to the OS platform you ran jlink on.  So on Windows, you'll have to substitute java.exe for java in the path above.

There's a way to cross-compile a Java Runtime for a different OS platform with jlink, but you'll need to download the target platform's JDK.  It was easier to run the target platform's OS in a virtual machine and run jlink on it instead.

A thorough and detailed tutorial is How to Create Java Runtime Images with jlink.


2020-12-23

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).

So...

  • 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.

2020-10-21

Quickly Open source code file location in OS's file browser from Netbeans

Want to open the file system browser to the location of a file or folder from Netbeans?

Easy, use the QuickOpener plugin.  Such a basic functionality requires a plugin, whereas it's built in in VS Code, but there it is.

Not the old QuickOpener that's been abandoned.

Use the new QuickOpener that's the fork of the old one (it's a friendly fork).

It works with Apache Netbeans, and can be found in the Netbeans plugin search area at least up to version 11.

For Netbeans version 12, you'll need to download the NBM plugin file from the online page of the new QuickOpener, then install it in Netbeans from the downloaded NBM file.  It worked for me in basic testing, so it should work fine.

2020-06-30

Stop Netbeans downloading whole 1GB maven index

Netbeans for Java programming with Maven likes to download the Maven index that's over 1 GB in size.

There's basically three ways to stop that huge download for 3 different situations:

(1) Temporarily don't want auto updates

If you already downloaded the index, the updates are smaller but still sizable.  One way to to stop it re-downloading the updates is to go to:

Tools > Options > Java > Maven > Index > Index update frequency > set to never.

Then click "Index Now" in that window only whenever you want an update.

(2) Just don't want Maven at all

If you don't have the index downloaded yet (e.g. a new install) and basically never want to use Maven, then in that same window, you could instead check off:

Completely disable indexing

As it warns you, lots of features will be disabled, but if you're not using Maven, who cares?

(3) Want Maven index without the download

This is amazing, there's this plugin you should get and it'll solve this problem: Maven Remote Search plugin.

It's old and it says it's for Netbeans 8.2 (the super old Oracle version), but I tried it out and it works for the new Apache Netbeans 11 and 12!

It lets you search the Maven index online rather than downloading the whole index to your local disk (which is crazy).

The github repo for the plugin is active recently with a historical build, so hopefully it'll get its version bumped and put on the Apache Netbeans plugins web page (which I don't think exists yet...).


Bibliography:

2017-04-02

Which programming language to teach? A principled choice

Java is still one of the most popular programming language to teach the young or newbies to programming.  It's a very problematic choice.  See:

  1. The problem of Object Oriented Programming is an education one
  2. Learn Python instead of Java as your first language [1]
  3. Java has deep expression problem for beginning students
  4. Governments mandating which programming language to teach
Having looked at some of the problems and issues before, I want to be constructive and offer some principles for how to choose which programming language to teach instead.


1. Principle of no magical incantations

This can be viewed as a language feature vs. library supplied functionality issue.  The latter is mostly okay, but the former should have no magical incantations that students need to learn.

Magical incantations are language features like the "static" keyword in Java.  You could imagine a student asking:
What does "static" mean in the "main" method declaration?  Why is it "static" and not something else?  What does "static" do?  Why do I need to write "static" when I don't know what it means to make something "static" vs not static?  I don't want it "static", I want it "grounded", can I write that instead?
Now you could imagine a teacher answering:
The answer to why, what, how, etc., would require explaining OOP and how it's implemented in Java and...  Look, just write 'static'.  It's just the way it is.  Just do it this way or else it doesn't work.  It's a magical incantation the Java gods require you to recite.
The more language features required to write even a simple program, the more things students have to learn or be ignorant of but use (i.e. magical incantations).

That makes it more likely that students have to learn everything about the programming language all at once just to do even the simplest thing at all.

2. Minimize concepts required to start doing stuff

The more that foundational programming concepts are required, the more programming language specific things students must think about whilst at the same time thinking about solving the actual (i.e. non-programming-language, "business") problem in its problem domain.

Otherwise, it'd be like students have to learn everything in the programming language all at once in order to do anything at all.

3. Idiomatic code from the start

A programming language that encourages writing idiomatic code from the very start reduces either the magical incantations required in writing idiomatic code, and reduces dumb code written stupidly just to avoid learning the magical incantations.

Otherwise, students have to learn everything all at once just to do anything at all.

Magical incantations are not hidden machinery!

I'm not advocating learning C because it doesn't have the magic of a garbage collector (GC)!  The GC is not a magical incantation: it's mostly hidden machinery.

Hidden machinery works quietly, never broadcasting its own existence, and isn't in your face about what it does.  It doesn't offer an affordance where none is called for, or where it would be inappropriate for the target user.

Magical incantations are flamboyant and in your face.  You know it's doing work because the magician is showing you that work is being done through the incantations, even if what's shown and what's done might very well be disconnected from each other.

To a newbie, the "static" Java keyword (to pick on something as an example) is magical incantation.  The Java GC is hidden machinery that we should be thankful for having every day.

Hidden machinery that makes a language easier for a newbie to learn is great.  Magical incantations that calls out its own existence is not helpful.

Magical incantations are also not Spooky Action at a Distance.  But that's a topic for another day.


Afterword
I wrote the above years ago (around 2013 February 4), and only now slightly expanded and lightly edited it to share here.

[1] I don't recommend learning Python as your first language anymore for various reasons (but I'd certainly recommend learning Python over Java as your first language!).

2015-03-27

Lynda.com for learning computing science as high school students: a review

Recently, I had a chance to spend some time reviewing Lynda.com's offerings on various computing science topics.  The review here is geared towards using Lynda.com with high school students as the target audience.  I thought I'd share a few observations.

Lynda.com is ok for what it is, that is, as a quick introduction to topics for what seems to be its intended audience of busy professionals working in the field.  At least I think that's their target audience.

For high school students, however, especially for beginner, intermediate, or even middle to lower level advanced high school students, Lynda.com's offerings for computing science topics are simply inadequate, missing curricular connections, and uses pedagogy ill-fitting for students in the high school age range.  That's not really a bad thing for Lynda.com, as I don't think high school students are their target audience at all.

2014-08-15

Java has deep expression problem for beginning students

There are many problems with Java as the first programming language to teach students if we wish to provide the most effective learning experience.  I've written on this in Learn Python instead of Java as your first language in the past even.  So what now?

Newbie, meet the Expression Problem

Stuart Sierra provides a very lucid explanation of the Expression Problem, a classic problem in software programming, in Solving the Expression Problem with Clojure 1.2.  Needless to say, Clojure provides a very clean solution.

Java, however, is a quagmire and requires some heavy OOP software engineering concepts to solve the Expression Problem.  One wouldn't ordinarily think this has anything to do with beginning students just learning to program though, but it does, and here's how.

Imagine our beginning student, "Sam", starts to learn Java and eventually starts to write a classic game of asteroids.  Sam plugs away and gets a decent game of a single player ship shooting lasers at one kind of asteroids to begin working.  Not bad!  But Sam wants to do more.  Sam wants to not just have one kind of (big) asteroids, he also wants to have small asteroids to shoot at.

Alright, so Sam begins to modify the BigAsteroids class to also be able to represent a smaller sized kind of asteroids.  The teacher catches wind of this and tells Sam, "no, that's not good", and that Sam needs to use OOP principles to write a different class for SmallAsteroids.

Now most students would say "why, Mr. Teach", my way works.  But Sam is a good student and does as he's told.

So Sam goes and creates a second class for SmallAsteroids.  Except his program was built presuming that the only things to draw, to shoot lasers at, and to move around, were BigAsteroids.  None of those methods he wrote to draw, to shoot lasers at, and to move around BigAsteroids work for SmallAsteroids.  hmm...  Welcome to the Expression Problem, Sam.

2012-01-02

Learning Java for first time programmers

I'm designing a course for first time programmers to learn Java.  Here are some useful resources I found that I like:

Interactive Tutorials
  1. Introduction to Computer Science using Java (Bradley Kjell)

Lecture Notes
  1. Introduction to Programming in Java (MIT OCW)

Textbooks
  1. Think Java: How to Think Like a Computer Scientist (Allen B. Downey) - suitable for AP Computer Science, so suitable for younger students
  2. Introduction to Programming Using Java, Sixth Edition (David J. Eck) - link not working for me right now but I've heard good things about it
  3. Introduction to Programming in Java (Robert Sedgewick, Kevin Wayne) - contains case studies connected to real scientific or business uses, but means requires students to have a more advanced math background more suitable for 2nd+ year university undergrad students.
  4. AP Computer Science A (Dec 31 2019 edition)  (Roselyn Teukolsky) - fantastic study and review book for Java, especially for studying for the College Board AP Computer Science A exam.  I've used this book in its various yearly editions before and can say this book is really good.

2011-11-22

Learn Python instead of Java as your first language

I'm struggling with figuring out which programming language to teach students would provide the most effective learning experience.

It's easy to find tons of statistics showing how Java is the most popular language with tons of community and books, etc.  That, however, doesn't say very much about the learning experience of the student at all, or what the students will come away with.

I found the following from a respected hacker in the community, for example:
"For example, if your company wants to write some software, it might seem a prudent choice to write it in Java. But when you choose a language, you're also choosing a community. The programmers you'll be able to hire to work on a Java project won't be as smart as the ones you could get to work on a project written in Python. And the quality of your hackers probably matters more than the language you choose. Though, frankly, the fact that good hackers prefer Python to Java should tell you something about the relative merits of those languages.

"Business types prefer the most popular languages because they view languages as standards. They don't want to bet the company on Betamax. The thing about languages, though, is that they're not just standards. If you have to move bits over a network, by all means use TCP/IP. But a programming language isn't just a format. A programming language is a medium of expression.

"I've read that Java has just overtaken Cobol as the most popular language. As a standard, you couldn't wish for more. But as a medium of expression, you could do a lot better. Of all the great programmers I can think of, I know of only one who would voluntarily program in Java. And of all the great programmers I can think of who don't work for Sun, on Java, I know of zero."  (Great Hackers, Paul Graham, 2004)
So essentially, the idea here is that if you choose a language based on whether it's the popular "standard", you've lost sight of the fact that programming is very much an art, and the language is a medium of expression — why would anyone wish upon students the torture of a lesser blub language?

Java is becoming the new Cobol since 2007.  So of course it's popular, but we probably wouldn't want students learning Cobol as their first language now either.

The better language is Python, according to the best hackers in the community known to Graham (and he knows plenty, given what he does as his "day job" now).


Consider this, also from a respected hacker in the community:
"If you don't know any computer languages, I recommend starting with Python. It is cleanly designed, well documented, and relatively kind to beginners. Despite being a good first language, it is not just a toy; it is very powerful and flexible and well suited for large projects.

"I used to recommend Java as a good language to learn early, but this critique has changed my mind (search for The Pitfalls of Java as a First Programming Language within it). A hacker cannot, as they devastatingly put it approach problem-solving like a plumber in a hardware store; you have to know what the components actually do." (How To Become A Hacker, Eric S. Raymond, 2008)
Here the essential idea, I think, is that Java can help you build stuff, but it doesn't help you very much in learning to think and express your thoughts programmatically.  Being good at putting together code in Java that uses what other people have written doesn't help you solve problems better in a hacking or engineering kind of way.


It gets worse for Java according to this critique, as ESR mentioned in the quote above, which details failings of teaching Java at the University undergrad level.

But I am interested in this question in terms of high school students.  The difference for high schools is that they may offer an AP or IB program, which may mandate the use of Java for their exams.  In that case, of course for the sake of writing an exam, Java must be taught.

Looking longer term, however, teaching Java as a first language in high school raises lots of questions (some already answered above).

2011-02-15

How to change JPEG compression in Java

Unless you use specialized libraries like JMagick, JAI, or access libjpeg through JNI, doing something simple like changing the JPEG compression in Java turned out to be excruciatingly tedious (or just hard to figure out the first time at least).  Here's how to do it:

(I'll explain how to do the following in Clojure as well.)

And the upshot is that this way, it seems you get to preserve the metadata from the original JPEG file — at least it did for me!

You will need these imports:

import java.io.File;
import javax.imageio.*;
import javax.imageio.stream.*;

First, we're going to need the default JPEG ImageReader and ImageWriter:

ImageReader imgRdr = ImageIO.getImageReadersByFormatName("jpg").next();
ImageWriter imgWrtr = ImageIO.getImageWritersByFormatName("jpg").next();

Next we'll need an ImageInputStream, wrapping around the JPEG File you want to convert the compression level of, and an ImageOutputStream, wrapping around the File location you want to save the re-compressed JPEG to:

ImageInputStream imgInStrm = ImageIO.createImageInputStream(inputJpegFile);
ImageOutputStream imgOutStrm = ImageIO.createImageInputStream(outputFile);

I assume you know how to create a File object to supply the parameters inputJpegFile and outputFile.

Now we mate the streams to the reader/writer: