TightVNC Java Viewer macOS用非公式パッチ 2022/6/17 新出@奈良女子大学 nide@ics.nara-wu.ac.jp TightVNC Java Viewerの現時点の最新版は2.8.3(約6年前…)ですが、macOS(の Java)の最近の版(いつからかはわかりませんが)では、以下のようなエラーで終 了してしまいます。 Exception in thread "main" java.lang.NullPointerException at com.glavsoft.viewer.swing.mac.MacApplicationWrapper. setEnabledAboutMenu(MacApplicationWrapper.java:95) at com.glavsoft.viewer.Viewer.main(Viewer.java:84) これは、com.apple.eawt.ApplicationクラスのsetEnabledAboutMenuメソッドがな くなってしまったのに、com.glavsoft.viewer.swing.mac.MacApplicationWrapper の中でそれをgetMethodしてきて呼ぼうとしていることに起因するようです。 そこで、setEnabledAboutMenuをgetMethodできなかった場合はそれを呼ばない ように書き直したところ、少なくとも手元のMacでは動くようになりました(ただ し、コンパイル時および実行時に使用するJavaのバージョンが7から11までであ ることが必要)。本品はそのパッチです。 パッチを当ててビルドしてできたjarは、元々のTightVNC Java Viewerと同じく java -jar tightvnc-jviewer.jar で動きます。なお、依然として実行時に WARNING: An illegal reflective access operation has occurred のメッセージは出ますが、それについては未対策です。 このパッチはパブリックドメイン扱いとします。また、言うまでもなく無保証 です。 (2024/4/19追記) 現在ではTightVNC以外にTigerVNCもJava Viewerを提供して おり、開発継続中のようですので、わざわざTightVNC向けのこのパッチを必要と することはもうあまりないでしょう。 [使い方] まず上述の通り、使用するJavaのバージョンが7〜11の間であることが必要で す。 TightVNCのダウンロードページの「Java Viewer source code」のリンクから、 tvnjviewer-2.8.3-src-gnugpl.zipを取ってきて展開し、このパッチを当ててから cd tvnjviewer-2.8.3; ./gradlew とします。メッセージの終わりの方に「BUILD SUCCESSFUL in ××s」と出てい ればビルド成功です。dist/tightvnc-jviewer-2.8.3/tightvnc-jviewer.jar が できていますので、それを使って下さい。なお、ビルド終了後は ~/.gradle は 消しても大丈夫です。 パッチ内でgradleのバージョン指定を変えている理由は、gradle 5.4.1以降で ないとJava 9以降のJavaのバージョンを正常に取得できないためです。 [In English] This patch aims to fix the `NullPointerException' error which occurs when TightVNC Java viewer 2.8.3 is run on recent macOS. Apply this patch to tvnjviewer-2.8.3-src-gnugpl.zip got from TightVNC download page, then execute cd tvnjviewer-2.8.3; ./gradlew and tightvnc-jviewer.jar will be built in dist/tightvnc-jviewer-2.8.3. (You will need Java version from 7 to 11.) This patch is in public domain, and with no warranty. diff -ru tvnjviewer-2.8.3.orig/build.gradle tvnjviewer-2.8.3/build.gradle --- tvnjviewer-2.8.3.orig/build.gradle 2016-09-19 13:16:24.000000000 +0900 +++ tvnjviewer-2.8.3/build.gradle 2022-06-17 13:56:48.000000000 +0900 @@ -177,8 +177,8 @@ } } -task wrapper(type: Wrapper) { - gradleVersion = '2.14' +task non_wrapper(type: Wrapper) { + gradleVersion = '5.4.1' } diff -ru tvnjviewer-2.8.3.orig/gradle/wrapper/gradle-wrapper.properties tvnjviewer-2.8.3/gradle/wrapper/gradle-wrapper.properties --- tvnjviewer-2.8.3.orig/gradle/wrapper/gradle-wrapper.properties 2016-09-19 13:16:24.000000000 +0900 +++ tvnjviewer-2.8.3/gradle/wrapper/gradle-wrapper.properties 2022-06-17 13:56:48.000000000 +0900 @@ -11,4 +11,4 @@ distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff -ru tvnjviewer-2.8.3.orig/gradlew tvnjviewer-2.8.3/gradlew --- tvnjviewer-2.8.3.orig/gradlew 2016-09-19 13:16:24.000000000 +0900 +++ tvnjviewer-2.8.3/gradlew 2022-06-17 13:57:10.000000000 +0900 @@ -157,4 +157,4 @@ eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" --no-daemon diff -ru tvnjviewer-2.8.3.orig/src/viewer_swing_api/java/com/glavsoft/viewer/swing/mac/MacApplicationWrapper.java tvnjviewer-2.8.3/src/viewer_swing_api/java/com/glavsoft/viewer/swing/mac/MacApplicationWrapper.java --- tvnjviewer-2.8.3.orig/src/viewer_swing_api/java/com/glavsoft/viewer/swing/mac/MacApplicationWrapper.java 2016-09-19 13:16:24.000000000 +0900 +++ tvnjviewer-2.8.3/src/viewer_swing_api/java/com/glavsoft/viewer/swing/mac/MacApplicationWrapper.java 2022-06-17 13:56:48.000000000 +0900 @@ -91,8 +91,10 @@ } public void setEnabledAboutMenu(boolean enable) throws CommonException { + Method m = setEnabledAboutMenuMethod.get(); + if(m == null) return; try { - setEnabledAboutMenuMethod.get().invoke(applicationInstance, enable); + m.invoke(applicationInstance, enable); } catch (IllegalAccessException e) { throw new CommonException("Cannot invoke com.apple.eawt.Application.setEnabledAboutMenu: " + e.getMessage()); } catch (InvocationTargetException e) {