Categories: C, Java

Building Info-ZIP Source Code

I have been working on building the OpenJDK for the Windows ARM64 platform. The make images command has been failing in Cygwin with errors such as:

Creating java.se.jmod
zip I/O error: Device or resource busy
zip error: Could not create output file (/cygdrive/d/dev/repos/jdk/build/windows-aarch64-server-release/support/src.zip)
make[4]: *** [ZipSource.gmk:79: /cygdrive/d/dev/repos/jdk/build/windows-aarch64-server-release/support/src.zip] Error 1
make[4]: *** Deleting file '/cygdrive/d/dev/repos/jdk/build/windows-aarch64-server-release/support/src.zip'
make[3]: *** [ZipSource.gmk:93: zip] Error 2
make[2]: *** [make/Main.gmk:389: zip-source] Error 2
make[2]: *** Waiting for unfinished jobs....

ERROR: Build failed for target 'images' in configuration 'windows-aarch64-server-release' (exit code 2)

One of the troubleshooting approaches I tried was to build an instrumented zip executable to replace Cygwin’s zip.exe. I started by searching for the Cygwin zip package. Someone was kind enough to have a link to the Cygwin zip package’s official page which in turn linked to the Cygwin zip packaging repository. This repo’s tree view shows a single file with source URIs for zip and that’s how I learned that this zip utility was Info-ZIP. The Zip 3.0 page has a link to Info-ZIP’s SourceForge site, from which the zip sources can be downloaded. I used curl in the Windows Terminal as follows:

curl -Lo zip30.tar.gz https://sourceforge.net/projects/infozip/files/Zip%203.x%20%28latest%29/3.0/zip30.tar.gz/download
tar xvf zip30.tar.gz
cd ./zip30
git init; git add *; git commit -m "Commit original Info-ZIP sources"

Now that we have the sources, let’s see how to build them. The scenario I’m working on is Windows specific so we need Visual Studio 2019 with the Desktop Development with C++ workload installed. I’ll be building a 32-bit zip executable. Launch the x86 Native Tools Command Prompt for VS 2019 and change to the zip30 source directory to start building. Some digging around reveals a makefile with build instructions (that seem one directory off). Here’s the command to build a 32-bit executable from the sources (note that building fails due to various errors that need to be addressed):

nmake -f win32\makefile.w32

Carriage Return (CR) Name Collisions

The first error is this rather cryptic mess of syntax errors:

Microsoft (R) Program Maintenance Utility Version 14.29.30133.0
Copyright (C) Microsoft Corporation.  All rights reserved.

        cl -nologo -c -W3 -O2 -DWIN32 -DASM_CRC -ML  zip.c
cl : Command line warning D9002 : ignoring unknown option '-ML'
zip.c
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18822): error C2143: syntax error: missing ':' before 'constant'
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18822): error C2143: syntax error: missing ';' before ':'
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18822): error C2059: syntax error: ':'
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18823): error C2143: syntax error: missing '{' before ':'
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18823): error C2059: syntax error: ':'
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18824): error C2059: syntax error: '}'
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18825): error C2059: syntax error: '}'
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um\winnt.h(18826): error C2059: syntax error: '}'
zip.c(5746): warning C4267: '=': conversion from 'size_t' to 'ush', possible loss of data
zip.c(5838): warning C4267: '=': conversion from 'size_t' to 'ush', possible loss of data
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133\bin\HostX86\x86\cl.EXE"' : return code '0x2'
Stop.

Some head banging (and not looking at the precompiler output from cl -c -W3 -O2 -DWIN32 -DASM_CRC /P zip.c carefully) leads to c – Compiler errors in WINNT.H after retargeting solution to latest SDK (10.0.18362) – Stack Overflow where the solution is rather simple: do not use the name CR to define the carriage return since it maps to a bitfield in one of the structs in winnt.h. See Rename CR identifier to avoid collisions with ARM64 structs in winnt.h by swesonga · Pull Request #2 · swesonga/Info-ZIP (github.com)

Outdated Linker Flags

The next error is a complaint about the /OPT:NOWIN98 flag.


        link -nologo user32.lib advapi32.lib /OPT:NOWIN98 /INCREMENTAL:NO /PDB:zip.pdb  /RELEASE zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj  crc32.obj crci386c.obj globals.obj deflate.obj trees.obj match32.obj win32.obj win32zip.obj nt.obj win32i64.obj zip.res
LINK : fatal error LNK1117: syntax error in option 'OPT:NOWIN98'
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133\bin\HostX86\x86\link.EXE"' : return code '0x45d'
Stop.

Turns out this option was removed in Visual Studio 2010 as per the Microsoft C/C++ change history since the linker no longer supports optimizing for Windows 98. This is clearly a safe flag to remove from the linker flags in win32\makefile.w32.

Update the Branding

  1. Change the VERSION string from “3.0” to “3.0-ioHardenedZIP”
  2. Update the REVDATE from “July 5th 2008” to the current date (“December 18th 2021” in my case)
  3. Update the about text to indicate that it is a custom build.

Testing the Zip Build

The sources should now build successfully in the x86 Native Tools Command Prompt for VS 2019. The OpenJDK build uses the -qru flags for creating zip files so we can easily test the zip executable by creating a zip of the Info-ZIP help and license text.

zip -h > help.txt
zip -h2 > help2.txt
zip -L > license.txt
zip -qru ./files.zip -i *.txt

We need to verify whether the zip was correctly created. Saving this for another day.

Building on Linux/macOS

[Update 2021-12-22] To build Info-ZIP on macOS, the way the memset function is detected needs to be fixed. Info-ZIP for either Linux or macOS can then be built using this command:

make -f unix/Makefile generic

Categories: DevOps, Java

Windows OpenJDK Development Environment Setup

I documented how to set up an OpenJDK build environment for macOS and for Ubuntu Linux. Here is how to do the same for a Windows x86-64 environment on a Windows x86-64 machine. To create a JDK build for a Windows ARM64 environment, see the last section of this post.

  1. Install Visual Studio Code.
  2. Install Git and set Visual Studio Code as Git’s default editor.
  3. Install Visual Studio 2019. Ensure the Desktop Development with C++ workload is selected so that the C++ compiler is available.
The Visual Studio Desktop development with C++ workload
  1. Install a boot JDK. I used winget, the Windows package manager, to do this as outlined in the OpenJDK Windows installation instructions.
winget search Microsoft.OpenJDK
winget install Microsoft.OpenJDK.17
Microsoft Build of OpenJDK with Hotspot 17.0.1+12 (x64) 
Please watt while Windows configures Microsoft Build of OpenJDK with 
Hotspot 170 1+12(x64) 
Time remaining 7 seconds
  1. Install Cygwin using the command below.
setup-x86_64.exe -q -P autoconf -P make -P unzip -P zip
  1. Launch Cygwin, clone the OpenJDK repo then run bash configure. This should output an error if there are any missing dependencies. Once that completes successfully, make images will build the OpenJDK code.
mkdir ~/repos
cd ~/repos
git clone https://github.com/openjdk/jdk
cd ~/repos/jdk
bash configure
make images

To try out the local JDK build, run java.exe in the build folder, e.g.

cd ~/repos/jdk/build/windows-x86_64-server-slowdebug
cd jdk/bin
./java.exe -version

Troubleshooting

Keep in mind that make images can fail due to Cygwin-specific issues. The only workaround may be to downgrade Cygwin to a version known to work well, as I had to do when I ran into segfaults when running make.

Windows ARM64 JDK

To create a JDK build for a Windows ARM64 machine (as of this posting), you still need to set up the Windows x86-64 environment as described above with the additional changes below.

  1. Launch the Visual Studio Installer then install the “MSVC v142 – VS 2019 C++ ARM64 build tools (Latest)” item.
  2. Run bash configure with the additional –openjdk-target argument as outlined at https://github.com/microsoft/openjdk-aarch64
bash configure --openjdk-target=aarch64-unknown-cygwin

Running the ARM64 JDK on x86-64?

I was curious to see what happens if you try to run the ARM64 Java build in Cygwin on x86-64:

User@Machine /cygdrive/c/dev/repos/jdk/build/windows-aarch64-server-release/jdk/bin
$ ./java -version
-bash: ./java: cannot execute binary file: Exec format error

In the Windows command line we get this message in the terminal and the subsequent dialog box:

C:\dev\repos\jdk\build\windows-aarch64-server-release\jdk\bin>.\java.exe
This version of C:\dev\repos\jdk\build\windows-aarch64-server-release\jdk\bin\java.exe is not compatible with the version of Windows you're running. Check your computer's system information and then contact the software publisher.
Machine Type Mismatch

Launching it from Windows Explorer fails with this error:

Platform mismatch launching ARM64 Java on Windows x86-64

Categories: DevOps, Java

Set up macOS for OpenJDK Development

Last week I bought a new MacBook Pro with the Apple M1 Chip and 16GB of RAM. These are the steps I used to set it up for building the OpenJDK codebase.

General macOS Configuration

  1. Set the OS appearance (theme). I tend to prefer dark theme.
  2. Set your Mac’s name (it bothers me when the terminal has some random host name). You might need to restart your terminal for this change to take effect.

Install Development Tools

Should any of the commands below fail, see the troubleshooting section at the end for possible workarounds.

  1. Install homebrew by running the recommended command (and see the troubleshooting section if there are any git errors):
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  1. Clone the OpenJDK repo:
mkdir ~/repos
cd ~/repos
git clone https://github.com/openjdk/jdk
  1. Install Xcode from the App Store. Xcode 13.1 is the most recent as of this post.
  2. Download and install the Xcode command line tools.
  3. Select the Xcode command line tools: launch Xcode then go to Preferences > Locations. Select Xcode 13.1 in the Command Line Tools dropdown as shown below.
Selecting the Command Line Tools in Xcode
  1. Install autoconf: brew install autoconf
  2. Install Visual Studio Code (optional)

Installing the Boot JDK

This was surprisingly straightforward. The instructions on how to install the Microsoft Build of OpenJDK on macOS comprise a single homebrew command:

brew install --cask microsoft-openjdk

Installing the Microsoft OpenJDK on macOS

Building the OpenJDK

Running bash configure in the JDK folder should display any missing dependencies. Any errors from bash configure will need to be resolved before running make images.

cd ~/repos/jdk
bash configure
make images

To browse through the contents of the build folder in finder:

open ~/repos/jdk/build/

To try out your new build, switch to the bin folder and check the Java version:

cd ~/repos/jdk/build/macosx-aarch64-server-release/jdk/bin
./java -version

Here is the output I get:

saint@Saints-MBP-2021 bin % ./java -version
openjdk version "18-internal" 2022-03-22
OpenJDK Runtime Environment (build 18-internal+0-adhoc.saint.jdk)
OpenJDK 64-Bit Server VM (build 18-internal+0-adhoc.saint.jdk, mixed mode)
saint@Saints-MBP-2021 bin % 

Troubleshooting

Homebrew Installation Failure

Installing homebrew appeared to be successful (last message output below) but there was a git error in the output!

==> Downloading and installing Homebrew..
remote: Enumerating objects: 345, done.
remote: Counting objects: 100% (297/297), done.
remote: Compressing objects: 100% (107/107), done.
remote: Total 345 (delta 227), reused 238 (delta 184), pack-reused 48
Receiving objects: 100% (345/345), 171.73 KiB | 971.00 KiB/s, done.
Resolving deltas: 100% (227/227),
completed with 54 local objects.
From https://github.com/Homebrew/brew
* [new branch]
dependabot/bundler/Librarv/Homebrew/sorbet-0.5.9396
-> origin/dependabot/bundler/Librarv/Homebrew/sorbet-0.5.9396
778de69b0..be908f679 master -> origin/master
* [new tag] 3.3.6 -> 3.3.6
HEAD is now at be908f679 Merge pull request #12502 from carlocab/bug-template
error: Not a valid ref: refs/remotes/origin/master
fatal: ambiguous argument
'refs/remotes/origin/master': unknown revision or path not in the working tree.
Use
"_-' to separate paths from revisions, like this:
'git <command> [<revision>...] - I<files...11
fatal: Could not resolve HEAD to a revision
Warning: /opt/homebrew/bin is not in your PATH.
Instructions on how to configure vour shell for Homebrew
can be found in the 'Next steps' section below.
==> Installation successful!

Here is the relevant error, which I was able to copy/paste (with some typos) from the PNG!!!

error: Not a valid ref: refs/remotes/origin/master
fatal: ambiguous argument
'refs/remotes/origin/master': unknown revision or path not in the working tree.

I thought I could keep chugging along merrily but other steps will fail if this is not addressed. Thankfully, https://stackoverflow.com/questions/65605282/trying-to-install-hugo-via-homebrew-could-not-resolve-head-to-a-revision already addressed how to fix this. I had to look up the -C flag in the git docs (it executes the command in the context of the specified directory).

git -C $(brew --repository homebrew/core) checkout master
Fixing the homebrew/core git repo

Autoconf Installation Failures

No available formula with the name “autoconf”

I ran into errors of the form No available formula with the name "autoconf" when attempting to install autoconf. However, this happen with the unresolved brew installation git issue described above. Once that was resolved, https://stackoverflow.com/questions/11552171/cant-install-software-using-brew-on-my-mac helpfully pointed out that autoconf is part of the command line tools package (hence step 4 in the instructions above).

[saint@Saints-MBP-2021 jk % brew install autoconf
fatal: Could not resolve HEAD to a revision
Running 'brew update --preinstall'
==> Homebrew is run entirelv by unpaid volunteers. Please consider donating:
https://github.com/Homebrew/brew#donations
==› Auto-updated Homebrew!
Updated 1 tap (homebrew/cask).
==> Updated Casks
dated 1 cask.
Warning: No available formula with the name
"autoconf"
==› Searching for similarlv named formulae.
Error: No similarly named formulae found.
==> Searching for a previously deleted formula (in the last month).
Error: No previously deleted formula found.
==> Searching taps on GitHub.
Error: No formulae found in taps.

No Such File or Directory @ dir_chdir

Setting up a build environment on my Intel MacBook Pro led to errors like this:

==> Installing autoconf dependency: m4
Error: No such file or directory @ dir_chdir - /usr/local/Cellar

The workaround from https://programmerah.com/brew-install-node-error-no-such-file-or-directory-dir_chdir-bottle-installation-failed-5943/ is to simply reinstall brew.

Missing Xcodebuild tool

One of my bash configure runs failed with this error:

checking for sdk name..
configure: error: No xcodebuild tool and no system framework headers found, use --with-sysroot or --with-sdk-name to provide a path to a valid SDK
/Users/saint/repos/idk/build/.configure-support/generated-configure.sh: line 84: 5: Bad file descriptor
configure exiting with result code 1

This was because the command line tools had not been selected in Xcode as show in step 6. This resolution came from https://stackoverflow.com/questions/17980759/xcode-select-active-developer-directory-error.


Categories: DevOps

Downgrading Cygwin

Last week I was trying to set up an OpenJDK build environment on my Windows 11 machine. Building the repo would fail due to segfaults when running make. The workaround is to downgrade Cygwin from 3.3 to 3.2:

  1. Launch the Cygwin setup program (setup-x86_64.exe).
  2. Change the View dropdown to Full.
  3. Enter cygwin into the search box then select the cygwin package..
  4. Open the cygwin package’s dropdown in the New column.
  5. Change the selection from Keep to the desired version as shown in the image below.
Cygwin Setup - Select Packages 
Select packages to install 
Full 
Pack age 
base-cyg',vin 
cygnin-debuginfo 
cygwin-devel 
cygwin-doc 
cygwin-x-doc 
cygwin32 
cygwin32-binutiIs 
cygwin32-binutiIs-debuginfo 
cygwin32-defaufMıantfest 
cygwi n 32-gcc-core 
cygwi n 32-gcc-debuginfo 
cyg n 32-gcc*oftran 
cygwin32-gcc-g++ 
cygwin32-gettext 
cygwin324ibbfd 
cygwin324ibiconv 
cygwin324ibtooI 
cygwin32%N32apiheadem 
cygwi n -ıuntime 
cygwin32-zIib 
Korg -serv Sh repon er 
Korg -serv er-cygwin shrepoft 
Side obsolete packages 
Src7 Categofies 
Uninstall 
Skip 
31.7-1 
3.1 .ı-ı 
3.12-1 
3.1.5-ı 
3.1.6-ı 
3.1.7-ı 
Size 
O 
kep Best 
Descfiption 
O 
Jest 
332-1 
321-1 
331-0,1.9814cfd8f693 (Test) 
331-0.2.6c1f49f83fde (Test) 
331- ı 
33.1-1 
Keep 
Reinstall 
L] Lhils 
Debug 
2,931k 
Intial base installation helper scıipt 
LIIBtion engine 
or cyg',vın 
pment files 
%fıc documentation including man pages 
yectfic document ation 
t toolchain 
ygwin 3%tt toolchain 
or cygwin32-binutiIs 
ication manifest for Cygwin32 toolchain 
Win 32btt toolchain (C, OpenMP) 
or cygwin32-gcc 
Win 32btt toolchain (Fortran) 
Win 32bt toolchain 
t for Cygwin 32bt toolchain 
Nin 32btt toolchain 
gwin 3%tt toolchain 
gwin 3%tt toolchain 
,gwin 3%tt toolchain 
veadem for Cygwin 3hit toolchain 
libs for Cygwin 3hit toolchain 
in 32btt toolchain 
A breakpad crashrepofter for Cygwin 
Debug info for xorg-servercygwincrashrepofter
Cygwin version selection
  1. Click on the Next button then verify that the downgrade is to the desired version.
Cygwin Setup - Review and confirm changes 
Review coriirm 
Uninstall cygwin 3 3 2-1 (automatically added) 
Install cygwin 3 2 0-1 
c
Reviewing cygwin downgrade version

Finish the setup process then launch cygwin and verify that the version is correct by running:

cygcheck -c Cygwin
Verifying cygwin version after downgrading

Categories: Compilers

Ubuntu VM Setup for OpenJDK Development

I’m using a Windows 10 physical machine for my OpenJDK 17 development. Unfortunately, I ran into some issues getting the environment set up to build the JDK on Windows. To work around this, I created a Linux virtual machine. Although the instructions for building on Linux are on the OpenJDK site, I would like to have all the instructions in one spot, hence this post.

Creating an Ubuntu VM in Hyper-V

  1. Download an LTS Ubuntu .iso from the Ubuntu Desktop download page. I selected Ubuntu 20.04.3 LTS.
  2. Go to New > Virtual Machine in Hyper-V manager.
    1. Enter your VM name, generation, memory amount and type
    2. Select the connection type (Default Switch) and create a new virtual hard disk
    3. Select “Install an operating system from a bootable CD/DVD-ROM” then enter the path to the downloaded .iso file then click on Finish.
    4. Before starting the VM, set the number of virtual processors (it defaults to 1, which is less than ideal)!
  3. Perform a normal Ubuntu installation including erasing the disk

Let us now review the more interesting steps – those related to configuring the Ubuntu environment.

Increase the Resolution of the Ubuntu Guest OS

The default 1024×768 screen resolution of the Ubuntu guest is rather restrictive. The solution to this comes from https://askubuntu.com/questions/384602/ubuntu-hyper-v-guest-display-resolution. We need to configure the Hyper-V Synthetic Video Frame Buffer Driver by adding ” video=hyperv_fb:1680×1050” to the GRUB_CMDLINE_LINUX_DEFAULT value in the /etc/default/grub file.

sudo apt-get install linux-image-extra-virtual
sudo apt-get install vim
sudo vim /etc/default/grub
sudo update-grub
reboot

Install the development dependencies

The table below lists the JDK build dependencies and the commands to install them.

ComponentInstallation Command
autoconfsudo apt-get install autoconf
Gitsudo apt-get install git
C Compilersudo apt-get install build-essential
X11 librariessudo apt-get install libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev
cupssudo apt-get install libcups2-dev
fontconfigsudo apt-get install libfontconfig1-dev
alsasudo apt-get install libasound2-dev
JDK Build Dependencies

This single command suffices to install all these components.

sudo apt-get install autoconf git build-essential libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev libcups2-dev libfontconfig1-dev libasound2-dev

Install a code editor

Download the Visual Studio Code .deb file from https://code.visualstudio.com/Download. We can then install VS Code by running:

sudo apt install ~/Downloads/code_1.62.3-1637137107

Install a Boot JDK

I use the Microsoft OpenJDK build as the boot JDK. Here are the Ubuntu instructions for Installing the Microsoft Build of OpenJDK:

# Valid values are only '18.04' and '20.04'
# For other versions of Ubuntu, please use the tar.gz package
ubuntu_release=`lsb_release -rs`
cd ~/Downloads/
wget https://packages.microsoft.com/config/ubuntu/${ubuntu_release}/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get install apt-transport-https
sudo apt-get update
sudo apt-get install msopenjdk-17

Verify that everything is working by running “java -version”

Clone and Build the JDK

Clone the JDK. Note that cloning a fork might be much slower than cloning the upstream Github repo! I was averaging about 60KiB/s on my rork whereas cloning the upstream OpenJDK was averaging 6 MiB/s when receiving objects!

mkdir ~/repos
cd ~/repos
git clone https://github.com/openjdk/jdk

The JDK repo can now be configured and built

cd jdk
bash configure
make images

The configure command should display any missing dependencies that it needs and a suggestion for how to install them.

To try out your new build, switch to the bin folder and check the Java version:

cd ~/repos/jdk/build/linux-x86_64-server-release/jdk/bin
./java -version

To browse through the contents of the build folder in a file manager:

xdg-open ./build


Categories: Compilers

Entering the Compiler Space

Last week was my first week in the Java engineering group. It has been about 11 years since I took a compiler course (while in the CS MS program at BYU). A quick review of the history of Java was in order. Turns out I last used Java in 2012 in grad school. That must have been Java SE 7 from 2011 and Java SE 6 before that. Since I have not been in the compiler space since then, I have a steep learning curve ahead. That is the exciting thing about technology though – there is always more to learn!

I am currently a programmer in the developer division at Microsoft so it was helpful going through some of the Java development with Microsoft documentation for a high level overview of all our offerings. Also informative given my long absence from Java-land were the docs on how to Transition from Java 7 to Java 8 and from Java 8 to Java 11. It hadn’t yet dawned on me by the time I read through these that the reason references to 8, 11, and 17 keep coming up is because they are LTS releases.

As a newbie to the Java development world, I started by watching this 2019 OpenJDK Development talk on how to become an OpenJDK contributor. It is a great overview of concepts like project roles (author, committer, reviewer, etc), the contributor agreement, and (perhaps most importantly to me), how to find an issue to work on and build the OpenJDK. The breakdown of commonly used terminology and abbreviations was great to have as well.

For an introduction to the hotspot compiler, I started going through “A Simple Graph-Based Intermediate Representation“. I ended up watching Cliff Click’s talk on The Sea of Nodes and the HotSpot JIT before I got that far along in the paper. It was fascinating seeing details such as the CPU L1/L2 cache size playing into the design! Some of the concepts that I need to review after that talk include:

The sea of nodes talk also revealed to me how little I know about companies in the Java space. I don’t think I had heard of Azul before, for example. In fact, it’s not just companies but also technologies! I was going through some build documentation when I ran into mentions of AdoptOpenJDK and Adoptium, both of which were foreign to me. I was glad though to see my old friend Eclipse doing well.

One of the most enjoyable things about being a programmer is working with very skilled people, especially watching them in action! I always learn a lot! My colleagues David and Mat were kind enough to pull me into their triage and reporting of [JDK-8277299] STACK_OVERFLOW in Java_sun_awt_shell_Win32ShellFolder2_getIconBits – Java Bug System so I could get my feet wet with how things are done in OpenJDK development.

The OpenJDK process is certainly different from the other open source communities I’ve been a part of (.NET and Mozilla Firefox). My manager and I poked around the bug DB to see what compiler starter bugs are out there. I picked bug [JDK-7077093] labelOper::label() should return Label& but since I must start out as an author, issues cannot be assigned to me. Unusual to me but the logic appears sound. Here is the query for C2 starter bugs.

Other highlights of the week were setting up my dev box to build the OpenJDK source code (unsuccessfully), discovering that compiler explorer is a thing (and an open source one at that), learning from my teammates how to investigate a failure of a fairly complex test on MacOS (they were using LLDB). I hope to write follow-up entries on these at some point.


Categories: Big Data

Exploring Apache’s Hadoop MapReduce Tutorial

In the last post, I described the straightforward process of setting up and Ubuntu VM in which to run Hadoop. Once you can successfully run the Hadoop MapReduce example in the MapReduce Tutorial, you may be interested in examining the source code using an IDE like Eclipse. To do so, install eclipse:

sudo apt-get install eclipse-platform

Some common Eclipse settings to adjust:

  1. Show line numbers (Window > Preferences > General > Editors > Text Editors > Show Line Numbers
  2. To make Eclipse use spaces instead of tabs (or vice versa), see this StackOverflow question.
  3. To auto-remove trailing whitespace in Eclipse, see this StackOverflow question.

To generate an Eclipse project for the Hadoop source code, the src/BUILDING.txt file lists these steps (which we cannot yet run):

cd ~/hadoop-2.7.4/src/hadoop-maven-pluggins
mvn install
cd ..
mvn eclipse:eclipse -DskipTests

To be able to run these commands, we need to install the packages required for building Hadoop. They are also listed in the src/BUILDING.txt file. For the VM we set up, we do not need to install the packages listed under Oracle JDK 1.7. Instead, run these commands to install Maven, native libraries, and ProtocolBuffer:

sudo apt-get -y install maven
sudo apt-get -y install build-essential autoconf automake libtool cmake zlib1g-dev pkg-config libssl-dev
sudo apt-get -y install libprotobuf-dev protobuf-compiler

Now here’s where things get interesting. The last command installs version 2.6.1 of the ProtocolBuffer. The src/BUILDING.txt file states that version 2.5.0 is required. Turns out they aren’t kidding – if you try generating the Eclipse project using version 2.6.1 (or some non 2.5.0 version), you’ll get an error similar to this one:

As suggested here and here, you can check the version by typing:

protoc --version

How do we install 2.5.0? Turns out we have to build ProtocolBuffer 2.5.0 from the source code ourselves but we need to grab the sources from Github now (unlike those now outdated instructions): https://github.com/google/protobuf/releases/tag/v2.5.0

mkdir ~/protobuf
cd ~/protobuf
wget https://github.com/google/protobuf/releases/download/v2.5.0/protobuf-2.5.0.tar.gz
tar xvzf protobuf-2.5.0.tar.gz
cd protobuf-2.5.0

Now follow the instructions in the README.txt file to build the source code.

./configure --prefix=/usr
make
make check
sudo make install
protoc --version

The output from the last command should now be “libprotoc 2.5.0“. Note: you most likely need to pass the –prefix option to ./configure to avoid errors like the one below.

Now we can finally generate the Eclipse project files for the Hadoop sources.

cd ~/hadoop-2.7.4/src/hadoop-maven-plugins
mvn install
cd ..
mvn eclipse:eclipse -DskipTests

Once project-file generation is complete:

  1. Type eclipse to launch the IDE.
  2. Go to the File > Import… menu option.
  3. Select the Existing Projects into Workspace option under General.
  4. Browse to the ~/hadoop-2.7.4/src folder in the Select root directory: input. A list of the projects in the src folder should be displayed.
  5. Click Finish to import the projects.

You should now be able to navigate to the WordCount.java file and inspect the various Hadoop classes.


Categories: Big Data

Setting up Apache Hadoop

As part of my Dynamic Big Data course, I have to set up a distributed file system to experiment with various mapreduce concepts. Let’s use Hadoop since it’s widely adopted. Thankfully, there are instructions on how to set up Apache Hadoop – we’re starting with a single cluster for now.

Once installation is complete, log onto the Ubuntu OS. Set up shared folders and enable the bidirectional clipboard as follows:

  1. From the VirtualBox Devices menu, choose Insert Guest Additions CD image… A prompt will be displayed stating that “VBOXADDITIONS_5.1.26_117224” contains software intended to be automatically started. Just click on the Run button to continue and enter the root password. When the guest additions installer completes, press Return to close the window when prompted.
  2. From the VirtualBox Devices menu, choose Shared Clipboard > Bidirectional. This enables two way clipboard functionality between the guest and host.
  3. From the VirtualBox Devices menu, choose Shared Folders > Shared Folders Settings… Click on the add Shared Folder button and enter a path to a folder on the host that you would like to be shared. Optionally select Auto-mount and Make Permanent.
  4. Open a terminal window. Enter these commands to mount the shared folder (assuming you named it vmshare in step 3 above):
mkdir ~/vmshare
sudo mount -t vboxsf -o uid=$UID,gid=$(id -g) vmshare ~/vmshare

To start installing the software we need, enter these commands:

sudo apt-get update
sudo apt install default-jdk

Next, get a copy of the Hadoop binaries from an Apache download mirror.

cd ~/Downloads
wget http://apache.cs.utah.edu/hadoop/common/hadoop-2.7.4/hadoop-2.7.4.tar.gz
mkdir ~/hadoop-2.7.4
tar xvzf hadoop-2.7.4.tar.gz -C ~/
cd ~/hadoop-2.7.4

The Apache Single Node Cluster Tutorial says to

export JAVA_HOME=/usr/java/latest

in the etc/hadoop/hadoop-env.sh script. On this Ubuntu setup, we end up needing to

export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/

If you skip setting up this export, running bin/hadoop will give this error:

Error: JAVA_HOME is not set and could not be found.

Note: I found that setting JAVA_HOME=/usr caused subsequent processes (like generating Eclipse projects from the source using mvn) to fail even though the steps in the tutorial worked just fine.

To verify that Hadoop is now configured and ready to run (in a non-distributed mode as a single Java process), execute the commands listed in the tutorial.

$ mkdir input
$ cp etc/hadoop/*.xml input
$ bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.4.jar grep input output 'dfs[a-z.]+'
$ cat output/*

The bin/hadoop jar command runs the code in the .jar file, specifically the code in Grep.java, passing it the last 3 arguments. The output should resemble this summary:

If you’re interested in the details of this example (e.g. to inspect Grep.java), examine the src subfolder. If you don’t need the binaries and just want to look at the code, you can wget it from a download mirror, e.g.:

wget http://apache.cs.utah.edu/hadoop/common/stable/hadoop-2.7.4-src.tar.gz

Categories: C++

Common C++ Standard Library Compiler Errors (by Rusty C++ Coders)

The first programming assignment in the Operating Systems course can be a challenge for students that haven’t written C++ code in a while. While working with the std::queue data structure in C++, it’s easy to make certain types of mistakes (especially if C++ isn’t your native tongue):

  1. Not “using namespace std” when using standard library containers. This can result in some ugly error messages in Visual Studio, e.g. error/warning codes C2143, C4430, and C2238 for the class member array below (is there a better way for students/developers to find out what is happening when they make such a trivial mistake)?
  2. Not understanding the assignment operator semantics on a container like a queue. If we write queue<type> myqueue = array[i]; we get a copy of the queue array[i] (we might have simply wanted a reference/alias). For such a mistake, the code obviously compiles but doesn’t function as intended.
  3. Declaring a fixed-sized data structure to hold all values from a variable-sized container! Runtime errors take care of informing students about this bug (if they’re not lucky enough to have almost empty variable-size containers). The correct declaration of dynamic arrays of templated items is also not usually obvious: T* all_elements = new T[dynamic_integer_size];

Categories: Windows

Fighting Windows Update Failures

For the past month or so, I have been unable to update my 7.5 year-old machine from Windows 10 Build 14393 because “we couldn’t connect to the update service”! Some folks online suggested trying the “Fix problems with Windows Update” wizard. Unfortunately (or fortunately), this Wizard identified a Potential Windows Update Database Error – but it couldn’t fix it!

The next idea was trying the system file checker as mentioned here. This tool did not find any issues on my filesystem. The DISM.exe commands seemed irrelevant so I took a quick peek at the Event Viewer. Lo and behold, a long list of WindowsUpdateFailure3 events. The supposed cure? These commands suggested in this thread (found by Googling “WindowsUpdateFailure3”).

net stop wuauserv
net stop cryptSvc
net stop bits
net stop msiserver
ren C:\Windows\SoftwareDistribution SoftwareDistribution.old
ren C:\Windows\System32\catroot2 Catroot2.old
net start wuauserv
net start cryptSvc
net start bits
net start msiserver

These didn’t solve the problem either. Digging around in log files led me to error code 0x80240438, but then again, no useful hints from queries on this code. The registry keys mentioned didn’t even exist on my machine. OK Google. Now there is a list of connection error codes, but of course it doesn’t include the one from the update failure log.

Desperation: what else haven’t I tried? This page with connection error codes mentions ensuring that http://*.update.microsoft.com is reachable. http://update.microsoft.com redirects to a page describing how to get the Windows 10 Creators Update now. Aha! I end up downloading and running the Windows 10 Upgrade tool. The update hangs (or appears to, after a couple of hours) at 25% so I simply hit the reset button hoping for the best. Sure enough, I end up back at build 14393 after a while. Desperation led me to try this tool again yesterday. I was encouraged to see that it actually downloaded an update to the Windows 10 Upgrade tool. When I popped in after rebooting to update, it was still at 25% but I decided to let it run overnight. Quite pleased was I this morning to come and find a Welcome screen prompting me to select my telemetry, etc, settings. I’m now finally running an up to date OS!