混淆的单个可执行 JAR 将无法连接到数据库

问题描述 投票:0回答:1

在使用 maven-asssembly 插件打包的单 jar 应用程序中,我无法让 hibernate 与 yGuard 很好地配合。应用程序在尝试创建实体管理器时无法初始化数据库连接。

运行使用 Maven 程序集插件创建的非混淆 jar 运行得很好。此外,使用外部

lib/
目录运行多文件 jar 效果很好。当我尝试创建一个也被混淆的单个 jar 时,我遇到了持久性问题。

有人可以看一下我的 yGuard 和 hibernate 配置来帮助我找出为什么混淆的 jar 无法正确连接到数据库吗?

这是我尝试过的:

  • 防止 yGuard 使用
    <keep>
    标签混淆我的持久层
  • 从存储在资源中的
    persistence.xml
    切换到编程式休眠配置

应用程序启动,但在初始化我的

Database
实用程序类时无法创建数据库连接:

public class Database {

    
    private static SessionFactory factory;

    static {
        Configuration configuration = new Configuration();
        configuration.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
        configuration.setProperty("hibernate.hbm2ddl.auto", "update");
        configuration.setProperty("javax.persistence.jdbc.driver", "org.h2.driver");
        configuration.setProperty("javax.persistence.jdbc.url",
                "jdbc:h2:file:./hyperaccsdb");
        configuration.addAnnotatedClass(Account.class);
        configuration.addAnnotatedClass(AccountCookie.class);
        configuration.addAnnotatedClass(EmailAccount.class);
        configuration.addAnnotatedClass(EmailInbox.class);
        configuration.addAnnotatedClass(EmailPlatform.class);
        configuration.addAnnotatedClass(Avatar.class);
        configuration.addAnnotatedClass(BrowserConfig.class);
        factory = configuration.buildSessionFactory();
    }

    public static EntityManager getEntityManager() {
        return factory.createEntityManager();
    }

}

这是我在尝试初始化数据库连接时得到的堆栈跟踪:

Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: Could not initialize class com.toughdata.autogrowth.persistence.Database                               13:36:54 [41/1289]
        at com.toughdata.autogrowth.persistence.dao.EmailPlatformDaoImpl.A(Unknown Source)
        at com.toughdata.autogrowth.B.F.A(Unknown Source)
        at com.toughdata.autogrowth.B.R.A(Unknown Source)
        at com.toughdata.autogrowth.C.M.A(Unknown Source)
        at com.toughdata.autogrowth.C.I.D(Unknown Source)
        at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
        at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313)
        at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
        at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
        at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
        at java.desktop/java.awt.Component.processMouseEvent(Component.java:6626)
        at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3389)
        at java.desktop/java.awt.Component.processEvent(Component.java:6391)
        at java.desktop/java.awt.Container.processEvent(Container.java:2266)
        at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5001)
        at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
        at java.desktop/java.awt.Component.dispatchEvent(Component.java:4833)
        at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
        at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
        at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
        at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
        at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
        at java.desktop/java.awt.Component.dispatchEvent(Component.java:4833)
        at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
        at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
        at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
        at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
        at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.ExceptionInInitializerError [in thread "SwingWorker-pool-2-thread-1"]
        at net.bytebuddy.implementation.bind.MethodDelegationBinder$AmbiguityResolver.<clinit>(Unknown Source)
        at net.bytebuddy.implementation.MethodDelegation.L(Unknown Source)
        at net.bytebuddy.implementation.MethodDelegation.B(Unknown Source)
        at org.hibernate.bytecode.internal.bytebuddy.ByteBuddyState$ProxyDefinitionHelpers$1.A(Unknown Source)
        at org.hibernate.bytecode.internal.bytebuddy.ByteBuddyState$ProxyDefinitionHelpers$1.run(Unknown Source)
        at org.hibernate.bytecode.internal.bytebuddy.ByteBuddyState$ProxyDefinitionHelpers.<init>(Unknown Source)
        at org.hibernate.bytecode.internal.bytebuddy.ByteBuddyState.<clinit>(Unknown Source)
        at org.hibernate.bytecode.internal.bytebuddy.BytecodeProviderImpl.<init>(Unknown Source)
        at org.hibernate.bytecode.internal.bytebuddy.BytecodeProviderImpl.<init>(Unknown Source)
        at org.hibernate.bytecode.internal.BytecodeProviderInitiator.A(Unknown Source)
        at org.hibernate.bytecode.internal.BytecodeProviderInitiator.W(Unknown Source)
        at org.hibernate.bytecode.internal.BytecodeProviderInitiator.A(Unknown Source)
        at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.A(Unknown Source)
        at org.hibernate.service.internal.AbstractServiceRegistryImpl.F(Unknown Source)
        at org.hibernate.service.internal.AbstractServiceRegistryImpl.G(Unknown Source)
        at org.hibernate.service.internal.AbstractServiceRegistryImpl.A(Unknown Source)
        at org.hibernate.boot.internal.SessionFactoryBuilderImpl.<init>(Unknown Source)
        at org.hibernate.boot.internal.SessionFactoryBuilderImpl.<init>(Unknown Source)
        at org.hibernate.boot.internal.DefaultSessionFactoryBuilderService.A(Unknown Source)
        at org.hibernate.boot.internal.MetadataImpl.ʦ(Unknown Source)
        at org.hibernate.cfg.Configuration.B(Unknown Source)
        at org.hibernate.cfg.Configuration.C(Unknown Source)
        at com.toughdata.autogrowth.persistence.Database.<clinit>(Unknown Source)
        at com.toughdata.autogrowth.persistence.dao.EmailPlatformDaoImpl.B(Unknown Source)
        at com.toughdata.autogrowth.B.O.A(Unknown Source)
        at com.toughdata.autogrowth.B.R.A(Unknown Source)
        at com.toughdata.autogrowth.C.M.A(Unknown Source)
        at com.toughdata.autogrowth.C.I$1.A(Unknown Source)
        at com.toughdata.autogrowth.C.I$1.doInBackground(Unknown Source)
        at java.desktop/javax.swing.SwingWorker$1.call(SwingWorker.java:304)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.desktop/javax.swing.SwingWorker.run(SwingWorker.java:343)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
        at java.base/java.lang.Thread.run(Thread.java:840)

这是我的

yGuard
蚂蚁任务:

                                <yguard>
                                    <inoutpair in="${project.jar.unobf}" out="${project.jar}" />
                                    <rename
                                        logfile="${project.build.directory}/${project.build.finalName}_renamelog.xml">
                                        <adjust replacePath="false">
                                            <include name="/resources/*" />
                                        </adjust>
                                        <adjust replaceContent="true" replaceContentSeparator=".">
                                            <include name="**/*.xml" />
                                            <include name="**/*.dll" />
                                            <include name="**/*.so" />
                                        </adjust>

                                        <keep>
                                            <method name="void main(java.lang.String[])"
                                                class="${mainclass}" />
                                            <class>
                                                <patternset>
                                                    <include name="**.*" />
                                                    <exclude name="com.toughdata.autogrowth.gui.*" />
                                                    <exclude
                                                        name="com.toughdata.autogrowth.automation.**.*" />
                                                    <exclude
                                                        name="com.toughdata.autogrowth.commands.**.*" />
                                                    <exclude name="com.toughdata.autogrowth.auth.*" />
                                                </patternset>
                                            </class>
                                            <field name="*">
                                                <patternset>
                                                    <include
                                                        name="com.toughdata.autogrowth.persistence.entities.*" />
                                                </patternset>
                                            </field>
                                            <field
                                                class="org.apache.logging.log4j.core.config.AppenderControlArraySet"
                                                name="appenderArray" />
                                            <field
                                                class="com.toughdata.autogrowth.persistence.Database"
                                                name="factory" />
                                        </keep>
                                    </rename>
                                </yguard>

编辑: 查看 yGuard 的重命名日志,我可以看到 Hibernate 类由于某种原因被重命名。我将向其中添加一条保留规则,看看会发生什么。我认为我的模式

**.*
应该排除它们,但也许我需要更具体。这是重命名日志的片段:

  <method class="org.hibernate.StaleObjectStateException" name="java.lang.String getEntityName()" map="&#x00a3;"/>
  <method class="org.hibernate.Metamodel" name="java.lang.String[] getImplementors(java.lang.String)" map="&#x00f3;"/>
  <field class="org.hibernate.UnknownProfileException" name="name" map="&#x00c0;"/>
  <method class="org.hibernate.UnknownProfileException" name="java.lang.String getName()" map="&#x00a4;"/>
  <method class="org.hibernate.CustomEntityDirtinessStrategy$AttributeInformation" name="org.hibernate.type.Type getType()" map="A"/>
  <method class="org.hibernate.CustomEntityDirtinessStrategy$AttributeInformation" name="java.lang.Object getLoadedValue()" map="B"/>
  <method class="org.hibernate.CustomEntityDirtinessStrategy$AttributeInformation" name="java.lang.String getName()" map="C"/>
  <method class="org.hibernate.CustomEntityDirtinessStrategy$AttributeInformation" name="int getAttributeIndex()" map="D"/>
  <method class="org.hibernate.CustomEntityDirtinessStrategy$AttributeInformation" name="org.hibernate.persister.entity.EntityPersister getContainingPersister()" map="E"/>
  <method class="org.hibernate.CustomEntityDirtinessStrategy$AttributeInformation" name="java.lang.Object getCurrentValue()" map="F"/>
  <method class="org.hibernate.CustomEntityDirtinessStrategy$AttributeChecker" name="boolean isDirty(org.hibernate.CustomEntityDirtinessStrategy$AttributeInformation)" map="A"/>
  <method class="org.hibernate.CustomEntityDirtinessStrategy$DirtyCheckContext" name="void doDirtyChecking(org.hibernate.CustomEntityDirtinessStrategy$AttributeChecker)" map="A"/>
  <method class="org.hibernate.CustomEntityDirtinessStrategy" name="boolean canDirtyCheck(java.lang.Object, org.hibernate.persister.entity.EntityPersister, org.hibernate.Session)" map="A"/>
  <method class="org.hibernate.CustomEntityDirtinessStrategy" name="boolean isDirty(java.lang.Object, org.hibernate.persister.entity.EntityPersister, org.hibernate.Session)" map="B"/>
  <method class="org.hibernate.CustomEntityDirtinessStrategy" name="void resetDirty(java.lang.Object, org.hibernate.persister.entity.EntityPersister, org.hibernate.Session)" map="C"/>
  <method class="org.hibernate.CustomEntityDirtinessStrategy" name="void findDirty(java.lang.Object, org.hibernate.persister.entity.EntityPersister, org.hibernate.Session, org.hibernate.CustomEntityDirtinessStrategy$DirtyCheckContext)" map="A"/>
  <class name="org.hibernate.CacheMode$1" map="1"/>
  <field class="org.hibernate.CacheMode$1" name="$SwitchMap$jakarta$persistence$CacheStoreMode" map="A"/>
  <field class="org.hibernate.CacheMode$1" name="$SwitchMap$jakarta$persistence$CacheRetrieveMode" map="B"/>
  <field class="org.hibernate.CacheMode" name="REFRESH" map="A"/>
  <field class="org.hibernate.CacheMode" name="GET" map="B"/>
  <field class="org.hibernate.CacheMode" name="retrieveMode" map="C"/>
  <field class="org.hibernate.CacheMode" name="$VALUES" map="D"/>
  <field class="org.hibernate.CacheMode" name="PUT" map="E"/>
  <field class="org.hibernate.CacheMode" name="NORMAL" map="F"/>
  <field class="org.hibernate.CacheMode" name="storeMode" map="G"/>
  <field class="org.hibernate.CacheMode" name="IGNORE" map="H"/>
  <method class="org.hibernate.CacheMode" name="boolean isGetEnabled()" map="A"/>
  <method class="org.hibernate.CacheMode" name="org.hibernate.CacheMode interpretExternalSetting(java.lang.String)" map="A"/>
  <method class="org.hibernate.CacheMode" name="jakarta.persistence.CacheStoreMode getJpaStoreMode()" map="B"/>
  <method class="org.hibernate.CacheMode" name="org.hibernate.CacheMode[] values()" map="values"/>
  <method class="org.hibernate.CacheMode" name="boolean isPutEnabled()" map="C"/>
  <method class="org.hibernate.CacheMode" name="org.hibernate.CacheMode fromJpaModes(jakarta.persistence.CacheRetrieveMode, jakarta.persistence.CacheStoreMode)" map="A"/>
  <method class="org.hibernate.CacheMode" name="org.hibernate.CacheMode valueOf(java.lang.String)" map="valueOf"/>
  <method class="org.hibernate.CacheMode" name="jakarta.persistence.CacheRetrieveMode getJpaRetrieveMode()" map="D"/>
  <field class="org.hibernate.TransientPropertyValueException" name="propertyName" map="i"/>
  <field class="org.hibernate.TransientPropertyValueException" name="transientEntityName" map="j"/>
  <field class="org.hibernate.TransientPropertyValueException" name="propertyOwnerEntityName" map="k"/>
  <method class="org.hibernate.TransientPropertyValueException" name="java.lang.String getMessage()" map="getMessage"/>
  <method class="org.hibernate.TransientPropertyValueException" name="java.lang.String getPropertyOwnerEntityName()" map="a"/>
  <method class="org.hibernate.TransientPropertyValueException" name="java.lang.String getTransientEntityName()" map="b"/>
  <method class="org.hibernate.TransientPropertyValueException" name="java.lang.String getPropertyName()" map="c"/>
  <field class="org.hibernate.LazyInitializationException" name="LOG" map="&#x00c1;"/>
  <method class="org.hibernate.SessionFactoryObserver" name="void sessionFactoryCreated(org.hibernate.SessionFactory)" map="A"/>
  <method class="org.hibernate.SessionFactoryObserver" name="void sessionFactoryClosing(org.hibernate.SessionFactory)" map="B"/>
  <method class="org.hibernate.SessionFactoryObserver" name="void sessionFactoryClosed(org.hibernate.SessionFactory)" map="C"/>
</map>
java hibernate jpa obfuscation yguard
1个回答
0
投票

看来我的问题来自于对 yGuard 的 keep 流程缺乏了解。查看keep日志后,我注意到Hibernate中的所有类名都被保留,但所有方法和字段都在改变。我最初的假设是,因为我保留了类,所以字段和方法也会保留。不是这种情况。当告诉 yGuard 保留外部库中的类时,您必须显式指定要保留的方法和字段的可见性。

以下是需要定义保留规则的方式:

<keep>
  <class methods="public" fields="public">
    <patternset>
       <include name="com.my.pattern.to.keep.*" />
    </patternset>
  </class>
</keep>
</keep>

这一切都在 yGuard 文档的

class
部分进行了解释:https://yworks.github.io/yGuard/task_documentation.html#the-class-element

© www.soinside.com 2019 - 2024. All rights reserved.