본문 바로가기
Java

HotSwap, LiveReload, HotDeploy, HotReload ???

by java개발자 2021. 7. 23.

JRebel이 유료화가 되었다.

JRebel 대신 DCEVM, springloaded를 사용하려고 하니 어느부분 버그가 있다. 제대로된 개발툴이 필요하다.

 

node.js 진영에 비해 java 생태계의 dev tool이 점점 밀리는 느낌이다. 아니면 유료화...

 

java에도 좋은 기능이 많지만 실제로 사용하는 예는 드물다...

proxy, classloader, ASM, javassist, javaagent, eclipse plugin,,

 

java1.8, eclipse로 spring web 개발을 한다고 가정하에

개발중에 소스코드를 변경시, 바로 적용하고 싶으면

1. Hot-swap

2. 서버 재가동

 

> 서버 재가동이 안전하지만 당연히 느리다. 컴퓨팅 속도를 높이면 가능할까?

서버 재가동을 빠르게 할 수 있는 방법을 먼저 찾아보자.

(DI 컴포넌트 스캔 방식이라면 package 범위를 제한해서 부분적으로 하도록 바꾸던지

CPU, RAM을 바꾸던지^^. 얼마나 높일 수 있을까?)

 

---

 

Hot-swap이 가능하게 할려면,

1-1. JRebel, DCEVM, springloaded처럼 bytecode를 바꿔야 한다.

1-1-1. *.class 파일을 바꾸던지

1-1-2. 클래스로더에 올릴때 바꾸던지

 

2. javaagent를 이용해서

파일의 변경사항을 watch하고, 클래스로더에 다시 올려야 한다.

 

3.spring이라면, 변경된 bean관리는 어떻게 하나? 의존성....

으... 복잡하네..

그냥 다시 실행하는게 나은가?

 

참고.

hotSwap을 할려면, GC까지 건드려야 하나?

https://blog.naver.com/asura71/30021992124

 

ClassLoader의 비밀

[Java의 비밀] .class는 어떻게 하여 실행되는 것일까? Java 프로그램을 작성하여 컴파일을 하면 항상 .c...

blog.naver.com

 

------------------------

 

DCEVM을 다시 살려보는 방법을 생각해보자.

  • springloaded는 javaagent만 지정하면 되는데,
  • DCEVM은 javaagent뿐만 아니라 jvm에 패치를 적용한다. java native까지 변경하나보다.

개발 환경

  • windows10
  • jre1.8.0_181
  • hotswap-agent-1.4.1.jar

 

DCEVM을 하면서 발생한 이슈 및 해결

0. hotSwap이 안된다.

해결:

javaagent 파일경로 뒤에 다음을 추가한다.

=autoHotswap=true

ex) -XXaltjvm=dcevm -javaagent:<PATH>\hotswap-agent-1.3.0.jar=autoHotswap=true

또는 hotswap-agent.properties내에 autoHotswap=true을 추가해야 한다.

 

1. bean id를 지정하지 않았을 경우

// applicationContext.xml
<bean class="org.mybatis.spring.SqlSessionTemplate">
	<constructor-arg ref="sqlSession"></constructor-arg>
</bean>

// BoardDAOMybatis.java
import org.mybatis.spring.SqlSessionTemplate;
@Repository
public class BoardDAOMybatis {
  @Autowired
  private SqlSessionTemplate sqlSessionTemplate;

...
}

현상: BoardDAOMybatis.java 소스코드를 수정하고, 화면을 리프레시 했을 때, 오류 메시지

No qualifying bean of type [org.mybatis.spring.SqlSessionTemplate] is defined: expected single matching bean but found 3: org.mybatis.spring.SqlSessionTemplate#0,org.mybatis.spring.SqlSessionTemplate#1,org.mybatis.spring.SqlSessionTemplate#2

이유: 소스코드를 수정해서 DCEVM이 작동하면서 아마도 bean 객체를 새로 생성해주나 보다. 그런데 예전 bean이 계속 남아 있는건가?

해결: id를 지정한다. (보통은 class만 지정해도 Autowired가 되지만, id까지 지정해서 좀더 확실하게!!)

<bean class="org.mybatis.spring.SqlSessionTemplate" id="sqlSessionTemplate">

 

2. context:property-placeholder기능인 *.properties 파일을 참조하지 못한다.

// applicationContext.xml
<context:property-placeholder location="classpath:config/database.properties" />

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="${jdbc.driver}" />
  <property name="url" value="${jdbc.url}" />
  <property name="username" value="${jdbc.username}" />
  <property name="password" value="${jdbc.password}" />
</bean>

현상: Message: Could not open JDBC Connection for transaction; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class '${jdbc.driver}'

이유: ??

해결: *.properteis 사용하지 말고, 직접 하드코딩.

 

3. mybatis의 mapper.xml은 수정해도 반영이 안된다.

이유: 당연하다. mapper.xml은 SqlSessionFactoryBean에서 xml 파일을 메모리에 올려서 사용하기 때문에, xml만 바꾼다고 해서 SqlSessionFactoryBean의 객체가 변경되지 않는다.

mapper.xml을 바꾸면 SqlSessionFactoryBean을 갱신해주면 되겠지만, DCEVM입장에서는 그것을 알 도리가 없으니...

뭔가 trigger 설정을 추가할 수 있다면 좋을텐데...;;

안되니... 여러 블로그에서는 RefreshableSqlSessionFactoryBean을 직접 만들어서 파일의 변경사항을 감시하는 방법으로 우회하고 있다.

> HotSwapAgent에 mybatis plugin이 있는데, 어떻게 사용하는지 모르겠다;;;

https://github.com/HotswapProjects/HotswapAgent/tree/master/plugin/hotswap-agent-mybatis-plugin

 

GitHub - HotswapProjects/HotswapAgent: Java unlimited redefinition of classes at runtime.

Java unlimited redefinition of classes at runtime. - GitHub - HotswapProjects/HotswapAgent: Java unlimited redefinition of classes at runtime.

github.com

> 블로그에 돌아다니는 RefreshableSqlSessionFactoryBean.java는 옛날 소스코드인듯. WatchService를 이용해서 간단하게 재구현해보자.

 

유용한 기능

1. hotswap-agent.properties

참고: https://github.com/HotswapProjects/HotswapAgent/blob/master/hotswap-agent-core/src/main/resources/hotswap-agent.properties

ex)
autoHotswap=true
LOGGER=info
#spring.basePackagePrefix=com.springbook

* spring.basePackagePrefix은 component scan을 hotswap에서 다시 해주는 것 같다.

실제 소스에서는 좁은 범위로 사용하다가, hotswap에서는 package 범위를 넓게 잡아주었는데, 결과적으로 넓게 컴포넌트 스캔이 이루어진다. (spring config에서 scan을 사용하므로, 여기서는 안해도 될듯)

 

2. VM arguments에 다음 추가

// to get feedback about reloaded classes

-XX:TraceRedefineClasses=1

 

최종 VM arguments

-XXaltjvm=dcevm -javaagent:<PATH>\hotswap-agent-1.4.1.jar -XX:TraceRedefineClasses=1

 

 

9. 고민...

exclude package는 어떻게 지정?

'Java' 카테고리의 다른 글

log4j2, jersey, jdk1.8  (0) 2021.12.30
java, oracle 시스템 마이그레이션시 주의  (0) 2018.04.12