최근에 웹 응용 프로그램에서 다음 오류가 발생했습니다.
java.lang.OutOfMemoryError: PermGen 공간
Tomcat 6 및 JDK 1.6에서 실행되는 일반적인 Hibernate/JPA + IceFaces/JSF 애플리케이션입니다. 분명히 이것은 응용 프로그램을 몇 번 재배포한 후에 발생할 수 있습니다.
그 원인은 무엇이며 그것을 피하기 위해 무엇을 할 수 있습니까? 문제를 해결하려면 어떻게 해야 합니까?
질문자 :Community Wiki
최근에 웹 응용 프로그램에서 다음 오류가 발생했습니다.
java.lang.OutOfMemoryError: PermGen 공간
Tomcat 6 및 JDK 1.6에서 실행되는 일반적인 Hibernate/JPA + IceFaces/JSF 애플리케이션입니다. 분명히 이것은 응용 프로그램을 몇 번 재배포한 후에 발생할 수 있습니다.
그 원인은 무엇이며 그것을 피하기 위해 무엇을 할 수 있습니까? 문제를 해결하려면 어떻게 해야 합니까?
해결책은 Tomcat이 시작될 때 JVM 명령줄에 다음 플래그를 추가하는 것이었습니다.
-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled
tomcat 서비스를 종료한 다음 Tomcat/bin 디렉토리로 이동하여 tomcat6w.exe를 실행하면 됩니다. "Java" 탭에서 "Java 옵션" 상자에 인수를 추가합니다. "확인"을 클릭한 다음 서비스를 다시 시작합니다.
오류가 발생 하면 지정된 서비스가 설치된 서비스로 존재하지 않습니다 .
tomcat6w //ES//servicename
여기서 servicename 은 services.msc에서 볼 수 있는 서버의 이름입니다.
출처: Eric's Agile Answers 에 대한 orx의 의견 .
-XX:MaxPermGen=128M
-XX:MaxPermSize=128M
시도하는 것이 좋습니다.
이 메모리 풀의 정확한 용도를 말할 수는 없지만 JVM에 로드되는 클래스 수와 관련이 있습니다. (따라서 tomcat에 대한 클래스 언로드를 활성화하면 문제를 해결할 수 있습니다.) 응용 프로그램이 실행 시 클래스를 생성하고 컴파일하는 경우 기본값보다 큰 메모리 풀이 필요할 가능성이 더 큽니다.
여러 배포 후에 발생하는 앱 서버 PermGen 오류는 컨테이너가 이전 앱의 클래스 로더에 보유하고 있는 참조로 인해 발생할 가능성이 큽니다. 예를 들어 사용자 정의 로그 수준 클래스를 사용하면 앱 서버의 클래스 로더가 참조를 보유하게 됩니다. jmap 및 jhat과 같은 최신(JDK6+) JVM 분석 도구를 사용하여 이러한 클래스 로더 간 누수를 감지하여 앱에서 계속 유지되는 클래스를 확인하고 사용을 재설계하거나 제거할 수 있습니다. 일반적인 용의자는 데이터베이스, 로거 및 기타 기본 프레임워크 수준 라이브러리입니다.
Classloader 누출: 두려운 "java.lang.OutOfMemoryError: PermGen space" 예외 및 특히 후속 게시물을 참조하십시오 .
사람들이 흔히 범하는 실수는 힙 공간과 permgen 공간이 같다고 생각하는 것인데, 이는 전혀 사실이 아닙니다. 힙에 많은 공간이 남아 있을 수 있지만 여전히 permgen에서 메모리가 부족할 수 있습니다.
PermGen에서 OutofMemory의 일반적인 원인은 ClassLoader입니다. 클래스가 JVM에 로드될 때마다 클래스 로더와 함께 모든 메타 데이터는 PermGen 영역에 보관되며 이를 로드한 클래스 로더가 가비지 수집 준비가 되면 가비지 수집됩니다. Classloader에 의해 로드된 모든 클래스가 메모리에 남아 있는 것보다 메모리 누수가 있는 경우 몇 번 반복하면 permGen이 메모리 부족을 야기합니다. 고전적인 예는 Tomcat의 Java.lang.OutOfMemoryError:PermGen Space 입니다 .
이제 이를 해결하는 두 가지 방법이 있습니다.
1. Memory Leak의 원인 또는 메모리 누수가 있는지 찾습니다.
-XX:MaxPermSize
및 -XX:PermSize
를 사용하여 PermGen 공간의 크기를 늘립니다.
자세한 내용은 Java 의 2 Solution of Java.lang.OutOfMemoryError 를 확인할 수도 있습니다.
Sun JVM의 경우 명령줄 매개변수 -XX:MaxPermSize=128m
을 사용합니다(필요한 크기는 128로 대체).
-XX:MaxPermSize=256m
시도하고 지속되면 -XX:MaxPermSize=512m
Eclipse ide를 사용하고 있으므로 VM 인수 에 -XX: MaxPermSize = 128m
(가장 잘 작동하는 것을 실험할 수 있음)을 추가했습니다. 대부분의 JVM에서 기본 PermSize 는 약 64MB 로 프로젝트에 클래스가 너무 많거나 많은 수의 문자열이 있는 경우 메모리가 부족합니다.
일식의 경우 answer 에도 설명되어 있습니다.
1단계 : 서버 탭에서 톰캣 서버를 더블 클릭합니다.
2단계 : 시작 Conf를 열고 기존 VM 인수 -XX: MaxPermSize = 128m
을 추가합니다.
복잡한 웹 응용 프로그램을 배포 및 배포 취소하는 동안에도 이 문제에 대해 머리를 맞대고 있었고 설명과 솔루션을 추가해야겠다고 생각했습니다.
Apache Tomcat에 애플리케이션을 배포하면 해당 앱에 대해 새 ClassLoader가 생성됩니다. 그런 다음 ClassLoader는 모든 응용 프로그램의 클래스를 로드하는 데 사용되며 배포 취소 시 모든 것이 멋지게 사라집니다. 그러나 실제로는 그리 간단하지 않습니다.
웹 애플리케이션의 수명 동안 생성된 하나 이상의 클래스는 어딘가에 ClassLoader를 참조하는 정적 참조를 보유합니다. 참조는 원래 정적이므로 가비지 수집의 양이 이 참조를 정리하지 않습니다. ClassLoader와 로드된 모든 클래스는 그대로 유지됩니다.
그리고 몇 번의 재배포 후에 OutOfMemoryError가 발생합니다.
이제 이것은 상당히 심각한 문제가 되었습니다. 각 재배포 후에 Tomcat이 다시 시작되도록 할 수 있지만, 이는 종종 실행 불가능한 애플리케이션 재배포가 아니라 전체 서버를 중단시킵니다.
그래서 대신 Apache Tomcat 6.0에서 작동하는 솔루션을 코드로 작성했습니다. 다른 응용 프로그램 서버에서 테스트한 적이 없으며 다른 응용 프로그램 서버에서 수정하지 않고는 작동하지 않을 가능성이 매우 높다는 점을 강조해야 합니다.
나는 또한 개인적으로 이 코드를 싫어 하며, 적절한 종료 및 정리 방법을 사용하도록 기존 코드를 변경할 수 있다면 아무도 이것을 "빠른 수정"으로 사용해서는 안 된다고 말하고 싶습니다. 이것이 사용되어야 하는 유일한 경우는 자체 정적 참조를 정리하는 수단을 제공하지 않는 코드가 의존하는 외부 라이브러리(제 경우에는 RADIUS 클라이언트였습니다)가 있는 경우입니다.
어쨌든, 코드와 함께. 이것은 서블릿의 destroy 메소드 또는 (더 나은 접근 방식) ServletContextListener의 contextDestroyed 메소드와 같이 애플리케이션이 배포 취소되는 지점에서 호출되어야 합니다.
//Get a list of all classes loaded by the current webapp classloader WebappClassLoader classLoader = (WebappClassLoader) getClass().getClassLoader(); Field classLoaderClassesField = null; Class clazz = WebappClassLoader.class; while (classLoaderClassesField == null && clazz != null) { try { classLoaderClassesField = clazz.getDeclaredField("classes"); } catch (Exception exception) { //do nothing } clazz = clazz.getSuperclass(); } classLoaderClassesField.setAccessible(true); List classes = new ArrayList((Vector)classLoaderClassesField.get(classLoader)); for (Object o : classes) { Class c = (Class)o; //Make sure you identify only the packages that are holding references to the classloader. //Allowing this code to clear all static references will result in all sorts //of horrible things (like java segfaulting). if (c.getName().startsWith("com.whatever")) { //Kill any static references within all these classes. for (Field f : c.getDeclaredFields()) { if (Modifier.isStatic(f.getModifiers()) && !Modifier.isFinal(f.getModifiers()) && !f.getType().isPrimitive()) { try { f.setAccessible(true); f.set(null, null); } catch (Exception exception) { //Log the exception } } } } } classes.clear();
java.lang.OutOfMemoryError: PermGen
공간 메시지는 영구 세대의 메모리 영역이 모두 소모되었음을 나타냅니다.
모든 Java 응용 프로그램은 제한된 양의 메모리를 사용할 수 있습니다. 특정 응용 프로그램이 사용할 수 있는 정확한 메모리 양은 응용 프로그램 시작 중에 지정됩니다.
Java 메모리는 다음 이미지에서 볼 수 있는 여러 영역으로 구분됩니다.
메타스페이스: 새로운 메모리 공간이 탄생합니다.
JDK 8 HotSpot JVM은 이제 클래스 메타데이터의 표현을 위해 기본 메모리를 사용하고 있으며 이를 Metaspace라고 합니다. Oracle JRockit 및 IBM JVM과 유사합니다.
좋은 소식은 더 이상 java.lang.OutOfMemoryError: PermGen
공간 문제가 없고 Java_8_Download 이상을 사용하여 더 이상 이 메모리 공간을 조정하고 모니터링할 필요가 없다는 것을 의미합니다.
또는 permgen을 sun의 jvm과 다르게 처리하는 JRockit으로 전환할 수 있습니다. 일반적으로 성능도 더 좋습니다.
http://www.oracle.com/technetwork/middleware/jrockit/overview/index.html
가장 먼저 할 수 있는 일은 영구 생성 힙 공간의 크기를 더 크게 만드는 것입니다. 이것은 일반적인 –Xms(초기 힙 크기 설정) 및 –Xmx(최대 힙 크기 설정) JVM 인수로는 수행할 수 없습니다. 언급한 바와 같이 영구 생성 힙 공간은 일반 Java 힙 공간과 완전히 분리되어 있고 이러한 인수는 이 일반 Java 힙 공간을 위한 공간입니다. 그러나 영구 생성 힙의 크기를 더 크게 만들기 위해(적어도 Sun/OpenJDK jvms에서) 사용할 수 있는 유사한 인수가 있습니다.
-XX:MaxPermSize=128m
기본값은 64m입니다.
이를 잘 처리하는 또 다른 방법은 클래스를 언로드하여 PermGen이 절대 소모되지 않도록 하는 것입니다.
-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled
그런 것들은 과거에 저에게 마법처럼 작용했습니다. 그러나 한 가지, permgen 스윕은 귀하가 만드는 모든 요청 또는 해당 라인을 따라 무언가에 대해 추가 2개의 요청을 생성하기 때문에 이들을 사용하는 데에는 상당한 성능 절충이 있습니다. 트레이드오프와 사용의 균형을 맞춰야 합니다.
이 오류에 대한 세부 정보를 찾을 수 있습니다.
http://faisalbhagat.blogspot.com/2014/09/java-outofmemoryerror-permgen.html
여기에서 이야기하는 문제가 있습니다. 제 시나리오는 eclipse-helios + tomcat + jsf이고 당신이 하고 있는 것은 간단한 애플리케이션을 tomcat에 배포하는 것입니다. 나는 여기에 같은 문제를 보여 주었고 다음과 같이 해결했습니다.
Eclipse에서 서버 탭으로 이동하여 내 경우에는 등록된 서버를 두 번 클릭합니다. Tomcat 7.0, 내 파일 서버 일반 등록 정보가 열립니다. "일반 정보" 섹션에서 "실행 구성 열기" 링크를 클릭하면 이 두 항목 끝에 추가된 VM 인수의 인수 탭에서 서버 옵션 실행이 열립니다.
-XX: MaxPermSize = 512m -XX: PermSize = 512m
그리고 준비.
요즘 가장 간단한 대답은 Java 8을 사용하는 것입니다.
더 이상 PermGen 공간 전용으로 메모리를 예약하지 않으므로 PermGen 메모리가 일반 메모리 풀과 혼합될 수 있습니다.
Java 8이 아무것도 하지 않는다고 불평하지 않으려면 -XXPermGen...=...
JVM 시작 매개변수를 모두 제거해야 합니다.
Java 옵션 텍스트 영역에 다음 줄을 추가합니다.
-XX:MaxPermSize=128m
Perm gen 공간 오류는 jvm이 코드를 실행할 공간을 제공하는 대신 큰 공간을 사용하기 때문에 발생합니다.
UNIX 운영 체제에서 이 문제에 대한 최상의 솔루션은 bash 파일의 일부 구성을 변경하는 것입니다. 다음 단계는 문제를 해결합니다.
터미널에서 gedit .bashrc
명령을 실행합니다.
다음 값으로 JAVA_OTPS
변수를 만듭니다.
export JAVA_OPTS="-XX:PermSize=256m -XX:MaxPermSize=512m"
bash 파일을 저장합니다. 터미널에서 exec bash 명령을 실행합니다. 서버를 다시 시작합니다.
이 접근 방식이 문제에 효과가 있기를 바랍니다. 8 미만의 Java 버전을 사용하는 경우 이 문제가 가끔 발생합니다. 그러나 Java 8을 사용하면 문제가 발생하지 않습니다.
영구 생성 크기를 늘리거나 GC 매개변수를 조정하는 것은 실제 메모리 누수가 있는 경우 도움이 되지 않습니다. 응용 프로그램이나 일부 타사 라이브러리가 사용하는 경우 클래스 로더 누수가 유일하고 영구적인 해결책은 이 누수를 찾아 수정하는 것입니다. 도움이 될 수 있는 여러 도구가 있으며 최근 도구 중 하나는 필요한 기능이 포함된 새 버전을 출시한 Plumbr입니다.
또한 웹 앱에서 log4j를 사용하는 경우 log4j 문서 에서 이 단락을 확인하십시오.
PropertyConfigurator.configureAndWatch("log4j.properties")
사용하는 경우 웹 앱 배포를 취소할 때 메모리 누수가 발생하는 것 같습니다.
나는 Hibernate + Eclipse RCP의 조합을 가지고 있으며 -XX:MaxPermSize=512m
및 -XX:PermSize=512m
사용해 보았고 그것은 나를 위해 일하는 것 같습니다.
-XX:PermSize=64m -XX:MaxPermSize=128m
합니다. MaxPermSize
증가를 시도할 수도 있습니다. 효과가 있기를 바랍니다. 저에게도 마찬가지입니다. MaxPermSize
만 설정해도 효과가 없었습니다.
몇 가지 답변을 시도했지만 마침내 작업을 수행한 유일한 것은 pom의 컴파일러 플러그인에 대한 이 구성이었습니다.
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <fork>true</fork> <meminitial>128m</meminitial> <maxmem>512m</maxmem> <source>1.6</source> <target>1.6</target> <!-- prevent PermGen space out of memory exception --> <!-- <argLine>-Xmx512m -XX:MaxPermSize=512m</argLine> --> </configuration> </plugin>
이것이 도움이되기를 바랍니다.
jrockit도 저를 위해 이것을 해결했습니다. 그러나 서블릿 재시작 시간이 훨씬 더 나빴기 때문에 프로덕션에서는 더 좋았지만 개발에서는 일종의 드래그였습니다.
메모리 구성은 앱의 특성에 따라 다릅니다.
뭐하세요?
처리된 거래 금액은 얼마입니까?
얼마나 많은 데이터를 로드하고 있습니까?
등.
등.
등
아마도 앱을 프로파일링하고 앱에서 일부 모듈을 정리하기 시작할 수 있습니다.
분명히 이것은 응용 프로그램을 몇 번 재배포 한 후에 발생할 수 있습니다.
Tomcat에는 핫 배포가 있지만 메모리를 소비합니다. 가끔씩 컨테이너를 다시 시작해 보세요. 또한 프로덕션 모드에서 실행하는 데 필요한 메모리 양을 알아야 합니다. 지금이 해당 연구에 적합한 시기인 것 같습니다.
그들은 Tomcat의 최신 버전(6.0.28 또는 6.0.29)이 서블릿 재배치 작업을 훨씬 더 잘 처리한다고 말합니다.
정확히 같은 문제가 발생했지만 불행히도 제안된 솔루션 중 어느 것도 실제로 효과가 없었습니다. 배포 중에 문제가 발생하지 않았으며 핫 배포도 하지 않았습니다.
제 경우에는 (최대 절전 모드를 통해) 데이터베이스에 연결하는 동안 웹 응용 프로그램을 실행하는 동안 동일한 지점에서 매번 문제가 발생했습니다.
이 링크 (앞서 언급)는 문제를 해결하기에 충분한 내부 정보를 제공했습니다. jdbc-(mysql)-driver를 WEB-INF에서 jre/lib/ext/ 폴더로 옮기면 문제가 해결된 것 같습니다. 최신 JRE로 업그레이드하려면 드라이버를 다시 설치해야 하므로 이것은 이상적인 솔루션이 아닙니다. 유사한 문제를 일으킬 수 있는 또 다른 후보는 log4j이므로 해당 항목도 이동하고 싶을 수 있습니다.
이러한 경우의 첫 번째 단계는 GC가 PermGen에서 클래스를 언로드할 수 있는지 확인하는 것입니다. 표준 JVM은 이와 관련하여 다소 보수적입니다. 클래스는 영원히 살기 위해 태어났습니다. 따라서 로드된 클래스는 더 이상 코드를 사용하지 않더라도 메모리에 남아 있습니다. 이것은 애플리케이션이 동적으로 많은 클래스를 생성하고 생성된 클래스가 더 오랜 기간 동안 필요하지 않을 때 문제가 될 수 있습니다. 이러한 경우 JVM이 클래스 정의를 언로드하도록 허용하는 것이 도움이 될 수 있습니다. 시작 스크립트에 구성 매개변수를 하나만 추가하면 됩니다.
-XX:+CMSClassUnloadingEnabled
기본적으로 이것은 false로 설정되어 있으므로 이를 활성화하려면 Java 옵션에서 다음 옵션을 명시적으로 설정해야 합니다. CMSClassUnloadingEnabled를 활성화하면 GC가 PermGen도 청소하고 더 이상 사용되지 않는 클래스를 제거합니다. 이 옵션은 UseConcMarkSweepGC도 아래 옵션을 사용하여 활성화된 경우에만 작동합니다. 따라서 ParallelGC 또는 Serial GC를 실행할 때 다음을 지정하여 GC를 CMS로 설정했는지 확인하십시오.
-XX:+UseConcMarkSweepGC
Tomcat에 더 많은 메모리를 할당하는 것은 적절한 해결책이 아닙니다.
올바른 솔루션은 컨텍스트가 삭제되고 다시 생성된 후 정리를 수행하는 것입니다(핫 배포). 해결책은 메모리 누수를 막는 것입니다.
Tomcat/Webapp 서버에서 드라이버(JDBC) 등록을 취소하는 데 실패했다는 메시지가 표시되면 해당 드라이버를 등록 취소하십시오. 이렇게 하면 메모리 누수가 중지됩니다.
ServletContextListener를 만들고 web.xml에서 구성할 수 있습니다. 다음은 샘플 ServletContextListener입니다.
import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Enumeration; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.apache.log4j.Logger; import com.mysql.jdbc.AbandonedConnectionCleanupThread; /** * * @author alejandro.tkachuk / calculistik.com * */ public class AppContextListener implements ServletContextListener { private static final Logger logger = Logger.getLogger(AppContextListener.class); @Override public void contextInitialized(ServletContextEvent arg0) { logger.info("AppContextListener started"); } @Override public void contextDestroyed(ServletContextEvent arg0) { logger.info("AppContextListener destroyed"); // manually unregister the JDBC drivers Enumeration<Driver> drivers = DriverManager.getDrivers(); while (drivers.hasMoreElements()) { Driver driver = drivers.nextElement(); try { DriverManager.deregisterDriver(driver); logger.info(String.format("Unregistering jdbc driver: %s", driver)); } catch (SQLException e) { logger.info(String.format("Error unregistering driver %s", driver), e); } } // manually shutdown clean up threads try { AbandonedConnectionCleanupThread.shutdown(); logger.info("Shutting down AbandonedConnectionCleanupThread"); } catch (InterruptedException e) { logger.warn("SEVERE problem shutting down AbandonedConnectionCleanupThread: ", e); e.printStackTrace(); } } }
여기에서 web.xml에서 구성합니다.
<listener> <listener-class> com.calculistik.mediweb.context.AppContextListener </listener-class> </listener>
"그들"은 6.0.29를 실행 중이고 모든 옵션을 설정한 후에도 동일한 문제가 있기 때문에 잘못되었습니다. 위에서 Tim Howland가 말했듯이 이러한 옵션은 피할 수 없는 일을 미룰 뿐입니다. 그들은 내가 재배포 할 때마다 대신 오류가 발생하기 전에 3 번 재배포 할 수 있습니다.
--launcher.XXMaxPermSize
, -XX:MaxPermSize
등의 매개변수를 설정한 후에도 여전히 동일한 오류가 발생하는 경우 Eclipse에서 버그가 있는 버전을 사용 중일 가능성이 큽니다. 일부 타사 응용 프로그램에 의해 설치되고 기본값으로 설정된 JRE. 이러한 버그 버전은 PermSize 매개변수를 선택하지 않으므로 설정에 관계없이 이러한 메모리 오류가 계속 발생합니다. 따라서 eclipse.ini에서 다음 매개변수를 추가하십시오.
-vm <path to the right JRE directory>/<name of javaw executable>
또한 Eclipse의 환경 설정에서 기본 JRE를 올바른 버전의 Java로 설정했는지 확인하십시오.
저에게 효과가 있었던 유일한 방법은 JRockit JVM이었습니다. MyEclipse 8.6이 있습니다.
JVM의 힙은 실행 중인 Java 프로그램에 의해 생성된 모든 객체를 저장합니다. Java는 new
연산자를 사용하여 개체를 만들고 새 개체에 대한 메모리는 런타임에 힙에 할당됩니다. 가비지 컬렉션은 프로그램에서 더 이상 참조하지 않는 개체에 포함된 메모리를 자동으로 해제하는 메커니즘입니다.
나는 비슷한 문제가 있었다. 내 것은 JDK 7 + Maven 3.0.2 + Struts 2.0 + Google GUICE 종속성 주입 기반 프로젝트입니다.
mvn clean package
명령을 실행할 때마다 다음 오류가 표시되고 "BUILD FAILURE"가 발생했습니다.
org.apache.maven.surefire.util.SurefireReflectionException: java.lang.reflect.InvocationTargetException; 중첩 예외는 java.lang.reflect.InvocationTargetException입니다. null java.lang.reflect.InvocationTargetException 원인: java.lang.OutOfMemoryError: PermGen 공간
위의 모든 유용한 팁과 트릭을 시도했지만 불행히도 아무도 나를 위해 일하지 않았습니다. 나를 위해 일한 것은 아래에 단계별로 설명되어 있습니다 :=>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
요소를 추가한 다음 아래 표시된 대로 -Xmx512m -XX:MaxPermSize=256m
을 전달하는 <argLine>
<configuration> <argLine>-Xmx512m -XX:MaxPermSize=256m</argLine> </configuration>
도움이 되길 바라며 즐거운 프로그래밍 하세요 :)
출처 : http:www.stackoverflow.com/questions/88235/dealing-with-java-lang-outofmemoryerror-permgen-space-error
Python이 해석되는 경우 .pyc 파일은 무엇입니까? (0) | 2023.04.30 |
---|---|
Chrome을 사용하여 XML 대신 JSON을 반환하도록 ASP.NET Web API를 얻으려면 어떻게 해야 합니까? (0) | 2023.04.30 |
루프에서 개체를 제거할 때 ConcurrentModificationException을 방지하면서 컬렉션을 반복합니다. (0) | 2023.04.30 |
파이썬에서 싱글톤 만들기 (0) | 2023.04.30 |
동시성과 병렬성의 차이점은 무엇입니까? (0) | 2023.04.30 |