【エラー解決方法】Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(…) が発生したときの対処法
目次
こんにちは。飯塚です。
Javaの環境構築でエラーが発生し、解決までに時間がかかったため、整理のために記事にしました。前半に解決方法をご紹介し、後半に詳細の解説をまとめていきます。
前提となるエラー再現環境
| 項目 | 詳細 |
|---|---|
| OS | Windows 11 |
| 言語 | Java 11 |
| IDE | Eclipse 2023-12 (4.30.0) |
| プロジェクト管理ツール | Maven |
エラーログ:「java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass」
エラーログは下記です。ざっくり言えば、一部のモジュールにアクセスできないため、とあるクラスの読み込みに失敗している、という内容です。
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not “opens java.lang” to unnamed module @7d68ef40
エラー再現プログラム
再現コードです。Persistenceを使用したDB接続の初期準備として行われる処理です。再現には同プロジェクト内に何かしらのEntityクラスも必要ですが、今回は重要ではないので省略しています。
import javax.persistence.Persistence;
public static void main(String[] args) {
Persistence.createEntityManagerFactory("env_local");
}
直接原因:ランタイムJREのバージョン誤り
JavaSE-11での実行を想定されたプロジェクトでしたが、ランタイムJREの設定が、JavaSE-21 (jdk-21.0.5) になっていたことが原因でした。Eclipseのバージョンが異なると、デフォルトのJavaのバージョンも異なります。

解決方法:ランタイムJREのバージョンを修正する
jdk-21.0.5 から jdk-11 を選択して実行すると、エラーが解消しました。
まずは右クリックします。

「実行」> 「実行の構成」を選択します。

「JRE」タブで正しいバージョンを選択します。あとは「適用」して「実行」します。

原因の詳細:JEP 403: Strongly Encapsulate JDK Internals によって、JDK内部APIへのアクセス制限が強化された
Java17 にバージョンが上がったタイミングで、セキュリティとメンテナンス性向上のため、JDK内部APIへのアクセス制限が強化されていました。
JEP 403: Strongly Encapsulate JDK Internals
この変更による影響がそのまま出ていたので、JREのバージョンを変えることで解消しました。
補足:エラーメッセージの内容を読み解く
エラーメッセージの各用語を読み解いて、意味を理解します。
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not “opens java.lang” to unnamed module @7d68ef40
| 単語 | 意味 |
|---|---|
| reflect | プログラムが実行時に自身の構造を調査し、操作する機能 |
| InaccessibleObjectException | Javaのアクセス制限に違反した、という例外 |
| ClassLoader | クラスのロードを担当するオブジェクト。クラスのバイナリ名を指定すると、クラス・ローダーはクラスの定義を構成するデータを見つけるか生成する |
| defineClass | バイトの配列をクラスClassのインスタンスに変換するメソッド |
| java.base | Javaプログラミングに不可欠な基本的な機能を提供し、他のすべてのモジュールの基礎となるもの |
単語の意味を読み解いて、ざっくりエラーメッセージを意訳すると下記です。
リフレクションを使用して、java.lang.ClassLoaderクラスのdefineClassにアクセスしようとしましたが失敗しました。
このメソッドはjava.baseモジュール内のjava.langパッケージに属しており、外部からのアクセスが制限されています。
無名モジュール(@7d68ef40)からこのメソッドにアクセスしようとしていますが、java.baseモジュールはjava.langパッケージを「opens」(公開)していないため、アクセスが拒否されています。
Persistence.createEntityManagerFactory()を実行するときに、Hibernateがリフレクションを使用してクラスを読み込むのがエラーのトリガーだったと思われます。
補足:エラーログの全文
少し長いですが、参考程度にエラーログの全文も貼ります。
Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: env_local] Unable to build Hibernate SessionFactory at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:954) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:884) at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:58) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39) at com.codematic.fw.core.commons.db.DBEntityManagerFacroty.createEntityManager(DBEntityManagerFacroty.java:55) at com.codematic.fw.core.commons.db.DBManager.createManager(DBManager.java:80) at com.codematic.fw.core.commons.db.DBManager.<init>(DBManager.java:39) at TestSample.main(TestSample.java:61) Caused by: org.hibernate.MappingException: Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:123) at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:77) at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:344) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:465) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:881) ... 7 more Caused by: org.hibernate.HibernateException: Unable to instantiate default tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer] at org.hibernate.tuple.entity.EntityTuplizerFactory.constructTuplizer(EntityTuplizerFactory.java:91) at org.hibernate.tuple.entity.EntityTuplizerFactory.constructDefaultTuplizer(EntityTuplizerFactory.java:116) at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:385) at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:509) at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:124) at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486) at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:96) ... 11 more Caused by: java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:74) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486) at org.hibernate.tuple.entity.EntityTuplizerFactory.constructTuplizer(EntityTuplizerFactory.java:88) ... 19 more Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @6a370f4 at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:391) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:367) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:315) at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:203) at java.base/java.lang.reflect.Method.setAccessible(Method.java:197) at javassist.util.proxy.SecurityActions.setAccessible(SecurityActions.java:103) at javassist.util.proxy.FactoryHelper.toClass2(FactoryHelper.java:181) at javassist.util.proxy.FactoryHelper.toClass(FactoryHelper.java:164) at javassist.util.proxy.ProxyFactory.createClass3(ProxyFactory.java:507) at javassist.util.proxy.ProxyFactory.createClass2(ProxyFactory.java:492) at javassist.util.proxy.ProxyFactory.createClass1(ProxyFactory.java:428) at javassist.util.proxy.ProxyFactory.createClass(ProxyFactory.java:400) at org.hibernate.proxy.pojo.javassist.JavassistProxyFactory.postInstantiate(JavassistProxyFactory.java:72) at org.hibernate.tuple.entity.PojoEntityTuplizer.buildProxyFactory(PojoEntityTuplizer.java:164) at org.hibernate.tuple.entity.AbstractEntityTuplizer.<init>(AbstractEntityTuplizer.java:157) at org.hibernate.tuple.entity.PojoEntityTuplizer.<init>(PojoEntityTuplizer.java:60) at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62) ... 22 more
参考記事
リフレクションアクセスの原則的な禁止について
JavaAPI仕様ClassLoader.defineClass
Java 20 で java.lang.Void をインスタンス化する
まとめ
いかがでしょうか。
バージョンが上がったときの変更点を抑えていなかったのと、リフレクションやClassLoaderのことを詳しく知らなかったため、解決に時間がかかりました。今回のエラーを通して学ぶきっかけができたのは嬉しかったです。
《関連記事》
アシスタントリーダー Iizuka 技術の入門・まとめ系を中心に書いてます。あとで読み返したいと感じていただける記事を目指しています。


