增加问题

pull/6/head
yuanguangxin 5 years ago
parent b40f301b71
commit 5cea6bacfe

@ -1,8 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="af7ffdf2-4ddc-4ed6-8222-60ed5acbc2ed" name="Default Changelist" comment="">
<list default="true" id="af7ffdf2-4ddc-4ed6-8222-60ed5acbc2ed" name="Default Changelist" comment="增加问题">
<change afterPath="$PROJECT_DIR$/src/contest/q1/Solution.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/contest/q2/Solution.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/contest/q4/Solution.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Rocket.md" beforeDir="false" afterPath="$PROJECT_DIR$/Rocket.md" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -66,11 +70,11 @@
</component>
<component name="RecentsManager">
<key name="CopyClassDialog.RECENTS_KEY">
<recent name="contest" />
<recent name="链表操作.q61_旋转链表" />
<recent name="链表操作.q19_删除链表的倒数第N个节点" />
<recent name="递归.q104_二叉树的最大深度" />
<recent name="快慢指针遍历.q876_链表的中间结点" />
<recent name="递归.q226_翻转二叉树" />
</key>
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/src/hash相关" />
@ -79,26 +83,13 @@
<recent name="$PROJECT_DIR$/src/q206/f1" />
</key>
</component>
<component name="RunManager" selected="Application.MinStack">
<configuration name="MinStack" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="栈相关.q155_最小栈.MinStack" />
<module name="LeetCode" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="栈相关.q155_最小栈.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<component name="RunManager" selected="Application.Solution (3)">
<configuration name="Solution (1)" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="分治法.q34_在排序数组中查找元素的第一个和最后一个位置.Solution" />
<option name="MAIN_CLASS_NAME" value="contest.test.Solution" />
<module name="LeetCode" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="分治法.q34_在排序数组中查找元素的第一个和最后一个位置.*" />
<option name="PATTERN" value="contest.test.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
@ -106,12 +97,12 @@
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="Solution (4)" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="数字操作.q202_快乐数.Solution" />
<configuration name="Solution (2)" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="contest.q1.Solution" />
<module name="LeetCode" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="数字操作.q202_快乐数.*" />
<option name="PATTERN" value="contest.q1.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
@ -119,12 +110,12 @@
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="Solution (5)" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="栈相关.q316_去除重复字母.Solution" />
<configuration name="Solution (3)" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="contest.q4.Solution" />
<module name="LeetCode" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="栈相关.q316_去除重复字母.*" />
<option name="PATTERN" value="contest.q4.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
@ -132,12 +123,12 @@
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="Solution (6)" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="栈相关.q32_最长有效括号.Solution" />
<configuration name="Solution (4)" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="contest.Solution" />
<module name="LeetCode" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="栈相关.q32_最长有效括号.*" />
<option name="PATTERN" value="contest.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
@ -146,11 +137,11 @@
</method>
</configuration>
<configuration name="Solution" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="双指针遍历.q42_接雨水.Solution" />
<option name="MAIN_CLASS_NAME" value="contest.q2.Solution" />
<module name="LeetCode" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="双指针遍历.q42_接雨水.*" />
<option name="PATTERN" value="contest.q2.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
@ -199,11 +190,11 @@
</configuration>
<recent_temporary>
<list>
<item itemvalue="Application.MinStack" />
<item itemvalue="Application.Solution (3)" />
<item itemvalue="Application.Solution (1)" />
<item itemvalue="Application.Solution (6)" />
<item itemvalue="Application.Solution (5)" />
<item itemvalue="Application.Solution (4)" />
<item itemvalue="Application.Solution" />
<item itemvalue="Application.Solution (2)" />
</list>
</recent_temporary>
</component>
@ -264,9 +255,21 @@
<workItem from="1585041029099" duration="2193000" />
<workItem from="1585219892120" duration="917000" />
<workItem from="1585223904505" duration="7719000" />
<workItem from="1585376676883" duration="530000" />
<workItem from="1585657110826" duration="2824000" />
<workItem from="1586968521346" duration="792000" />
<workItem from="1585376676883" duration="673000" />
<workItem from="1585460780308" duration="4000" />
<workItem from="1586005610200" duration="115000" />
<workItem from="1586346473200" duration="613000" />
<workItem from="1586846888542" duration="1313000" />
<workItem from="1587193343846" duration="24885000" />
<workItem from="1587225096292" duration="132000" />
<workItem from="1588302756697" duration="3439000" />
</task>
<task id="LOCAL-00013" summary="update q98">
<created>1581156795852</created>
<option name="number" value="00013" />
<option name="presentableId" value="LOCAL-00013" />
<option name="project" value="LOCAL" />
<updated>1581156795852</updated>
</task>
<task id="LOCAL-00014" summary="add q110/q450/q701">
<created>1581270301073</created>
@ -590,28 +593,21 @@
<option name="project" value="LOCAL" />
<updated>1585234195148</updated>
</task>
<task id="LOCAL-00060" summary="新增JVM性能监控/调优相关">
<created>1585657673868</created>
<task id="LOCAL-00060" summary="add q62">
<created>1585377224497</created>
<option name="number" value="00060" />
<option name="presentableId" value="LOCAL-00060" />
<option name="project" value="LOCAL" />
<updated>1585657673869</updated>
<updated>1585377224497</updated>
</task>
<task id="LOCAL-00061" summary="update jvm">
<created>1585658308922</created>
<task id="LOCAL-00061" summary="增加问题">
<created>1586355292587</created>
<option name="number" value="00061" />
<option name="presentableId" value="LOCAL-00061" />
<option name="project" value="LOCAL" />
<updated>1585658308922</updated>
</task>
<task id="LOCAL-00062" summary="update jvm">
<created>1585658338742</created>
<option name="number" value="00062" />
<option name="presentableId" value="LOCAL-00062" />
<option name="project" value="LOCAL" />
<updated>1585658338743</updated>
<updated>1586355292587</updated>
</task>
<option name="localTasksCounter" value="63" />
<option name="localTasksCounter" value="62" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
@ -687,9 +683,9 @@
<MESSAGE value="add q64" />
<MESSAGE value="add q155" />
<MESSAGE value="add q61" />
<MESSAGE value="新增JVM性能监控/调优相关" />
<MESSAGE value="update jvm" />
<option name="LAST_COMMIT_MESSAGE" value="update jvm" />
<MESSAGE value="add q62" />
<MESSAGE value="增加问题" />
<option name="LAST_COMMIT_MESSAGE" value="增加问题" />
</component>
<component name="WindowStateProjectService">
<state x="320" y="115" key="#Inspections" timestamp="1581061018990">
@ -700,92 +696,92 @@
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="320" y="115" key="#Project_Structure/0.0.1440.900@0.0.1440.900" timestamp="1580830129378" />
<state x="533" y="166" key="#com.intellij.ide.util.MemberChooser" timestamp="1578548165321">
<state x="458" y="204" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog" timestamp="1587221348872">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="533" y="166" key="#com.intellij.ide.util.MemberChooser/0.0.1440.900@0.0.1440.900" timestamp="1578548165321" />
<state x="303" y="50" key="CommitChangelistDialog2" timestamp="1585658338467">
<state x="458" y="204" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog/0.0.1440.900@0.0.1440.900" timestamp="1587221348872" />
<state x="303" y="50" key="CommitChangelistDialog2" timestamp="1588336168121">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="303" y="50" key="CommitChangelistDialog2/0.0.1440.900@0.0.1440.900" timestamp="1585658338467" />
<state x="143" y="78" width="1152" height="720" key="DiffContextDialog" timestamp="1585657797990">
<state x="303" y="50" key="CommitChangelistDialog2/0.0.1440.900@0.0.1440.900" timestamp="1588336168121" />
<state x="143" y="78" width="1152" height="720" key="DiffContextDialog" timestamp="1588336167223">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="143" y="78" width="1152" height="720" key="DiffContextDialog/0.0.1440.900@0.0.1440.900" timestamp="1585657797990" />
<state x="143" y="78" width="1152" height="720" key="DiffContextDialog/0.0.1440.900@0.0.1440.900" timestamp="1588336167223" />
<state x="144" y="78" width="1152" height="720" key="DiffContextDialog/0.23.1440.793@0.23.1440.793" timestamp="1582714686712" />
<state x="143" y="78" width="1152" height="720" key="DiffContextDialog/0.23.1440.797@0.23.1440.797" timestamp="1585232660808" />
<state width="1398" height="303" key="GridCell.Tab.0.bottom" timestamp="1585235047508">
<state x="143" y="78" width="1152" height="720" key="DiffContextDialog/0.23.1440.797@0.23.1440.797" timestamp="1588303139733" />
<state width="1398" height="204" key="GridCell.Tab.0.bottom" timestamp="1587225087588">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state width="1398" height="303" key="GridCell.Tab.0.bottom/0.0.1440.900@0.0.1440.900" timestamp="1585235047508" />
<state width="1398" height="245" key="GridCell.Tab.0.bottom/0.23.1440.797@0.23.1440.797" timestamp="1585228590486" />
<state width="1398" height="303" key="GridCell.Tab.0.center" timestamp="1585235047507">
<state width="1398" height="204" key="GridCell.Tab.0.bottom/0.0.1440.900@0.0.1440.900" timestamp="1587225087588" />
<state width="1398" height="245" key="GridCell.Tab.0.bottom/0.23.1440.797@0.23.1440.797" timestamp="1587203529573" />
<state width="1398" height="204" key="GridCell.Tab.0.center" timestamp="1587225087587">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state width="1398" height="303" key="GridCell.Tab.0.center/0.0.1440.900@0.0.1440.900" timestamp="1585235047507" />
<state width="1398" height="245" key="GridCell.Tab.0.center/0.23.1440.797@0.23.1440.797" timestamp="1585228590484" />
<state width="1398" height="303" key="GridCell.Tab.0.left" timestamp="1585235047506">
<state width="1398" height="204" key="GridCell.Tab.0.center/0.0.1440.900@0.0.1440.900" timestamp="1587225087587" />
<state width="1398" height="245" key="GridCell.Tab.0.center/0.23.1440.797@0.23.1440.797" timestamp="1587203529571" />
<state width="1398" height="204" key="GridCell.Tab.0.left" timestamp="1587225087586">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state width="1398" height="303" key="GridCell.Tab.0.left/0.0.1440.900@0.0.1440.900" timestamp="1585235047506" />
<state width="1398" height="245" key="GridCell.Tab.0.left/0.23.1440.797@0.23.1440.797" timestamp="1585228590483" />
<state width="1398" height="303" key="GridCell.Tab.0.right" timestamp="1585235047507">
<state width="1398" height="204" key="GridCell.Tab.0.left/0.0.1440.900@0.0.1440.900" timestamp="1587225087586" />
<state width="1398" height="245" key="GridCell.Tab.0.left/0.23.1440.797@0.23.1440.797" timestamp="1587203529570" />
<state width="1398" height="204" key="GridCell.Tab.0.right" timestamp="1587225087587">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state width="1398" height="303" key="GridCell.Tab.0.right/0.0.1440.900@0.0.1440.900" timestamp="1585235047507" />
<state width="1398" height="245" key="GridCell.Tab.0.right/0.23.1440.797@0.23.1440.797" timestamp="1585228590484" />
<state width="1398" height="303" key="GridCell.Tab.1.bottom" timestamp="1585235047510">
<state width="1398" height="204" key="GridCell.Tab.0.right/0.0.1440.900@0.0.1440.900" timestamp="1587225087587" />
<state width="1398" height="245" key="GridCell.Tab.0.right/0.23.1440.797@0.23.1440.797" timestamp="1587203529572" />
<state width="1398" height="204" key="GridCell.Tab.1.bottom" timestamp="1587225087590">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state width="1398" height="303" key="GridCell.Tab.1.bottom/0.0.1440.900@0.0.1440.900" timestamp="1585235047510" />
<state width="1398" height="204" key="GridCell.Tab.1.bottom/0.0.1440.900@0.0.1440.900" timestamp="1587225087590" />
<state width="1398" height="304" key="GridCell.Tab.1.bottom/0.23.1440.797@0.23.1440.797" timestamp="1580408030266" />
<state width="1398" height="303" key="GridCell.Tab.1.center" timestamp="1585235047509">
<state width="1398" height="204" key="GridCell.Tab.1.center" timestamp="1587225087589">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state width="1398" height="303" key="GridCell.Tab.1.center/0.0.1440.900@0.0.1440.900" timestamp="1585235047509" />
<state width="1398" height="204" key="GridCell.Tab.1.center/0.0.1440.900@0.0.1440.900" timestamp="1587225087589" />
<state width="1398" height="304" key="GridCell.Tab.1.center/0.23.1440.797@0.23.1440.797" timestamp="1580408030265" />
<state width="1398" height="303" key="GridCell.Tab.1.left" timestamp="1585235047509">
<state width="1398" height="204" key="GridCell.Tab.1.left" timestamp="1587225087588">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state width="1398" height="303" key="GridCell.Tab.1.left/0.0.1440.900@0.0.1440.900" timestamp="1585235047509" />
<state width="1398" height="204" key="GridCell.Tab.1.left/0.0.1440.900@0.0.1440.900" timestamp="1587225087588" />
<state width="1398" height="304" key="GridCell.Tab.1.left/0.23.1440.797@0.23.1440.797" timestamp="1580408030262" />
<state width="1398" height="303" key="GridCell.Tab.1.right" timestamp="1585235047510">
<state width="1398" height="204" key="GridCell.Tab.1.right" timestamp="1587225087589">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state width="1398" height="303" key="GridCell.Tab.1.right/0.0.1440.900@0.0.1440.900" timestamp="1585235047510" />
<state width="1398" height="204" key="GridCell.Tab.1.right/0.0.1440.900@0.0.1440.900" timestamp="1587225087589" />
<state width="1398" height="304" key="GridCell.Tab.1.right/0.23.1440.797@0.23.1440.797" timestamp="1580408030266" />
<state x="431" y="173" key="MultipleFileMergeDialog" timestamp="1586968741746">
<state x="431" y="173" key="MultipleFileMergeDialog" timestamp="1588302773046">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="431" y="173" key="MultipleFileMergeDialog/0.0.1440.900@0.0.1440.900" timestamp="1586968741746" />
<state x="431" y="173" key="MultipleFileMergeDialog/0.0.1440.900@0.0.1440.900" timestamp="1588302773046" />
<state x="221" y="63" key="SettingsEditor" timestamp="1585223890241">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="221" y="63" key="SettingsEditor/0.0.1440.900@0.0.1440.900" timestamp="1585223890241" />
<state x="474" y="173" key="VCS.ChangeListViewerDialog" timestamp="1585577172815">
<state x="320" y="190" key="Vcs.Push.Dialog.v2" timestamp="1586355294634">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="474" y="173" key="VCS.ChangeListViewerDialog/0.0.1440.900@0.0.1440.900" timestamp="1585577172815" />
<state x="320" y="190" key="Vcs.Push.Dialog.v2" timestamp="1585658339806">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="320" y="190" key="Vcs.Push.Dialog.v2/0.0.1440.900@0.0.1440.900" timestamp="1585658339806" />
<state x="320" y="190" key="Vcs.Push.Dialog.v2/0.0.1440.900@0.0.1440.900" timestamp="1586355294634" />
<state x="100" y="100" width="1240" height="700" key="com.intellij.history.integration.ui.views.DirectoryHistoryDialog" timestamp="1581744794182">
<screen x="0" y="23" width="1440" height="797" />
</state>
<state x="100" y="100" width="1240" height="700" key="com.intellij.history.integration.ui.views.DirectoryHistoryDialog/0.23.1440.797@0.23.1440.797" timestamp="1581744794182" />
<state x="503" y="374" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2" timestamp="1586968733599">
<state x="100" y="100" width="1240" height="700" key="com.intellij.history.integration.ui.views.FileHistoryDialog" timestamp="1587219014962">
<screen x="0" y="23" width="1440" height="797" />
</state>
<state x="100" y="100" width="1240" height="700" key="com.intellij.history.integration.ui.views.FileHistoryDialog/0.23.1440.797@0.23.1440.797" timestamp="1587219014962" />
<state x="503" y="374" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2" timestamp="1588302762834">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="503" y="374" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2/0.0.1440.900@0.0.1440.900" timestamp="1586968733599" />
<state x="503" y="374" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2/0.0.1440.900@0.0.1440.900" timestamp="1588302762834" />
<state x="100" y="100" width="1240" height="700" key="dock-window-1" timestamp="1585037767258">
<screen x="0" y="23" width="1440" height="797" />
</state>
<state x="100" y="100" width="1240" height="700" key="dock-window-1/0.23.1440.797@0.23.1440.797" timestamp="1585037767258" />
<state x="378" y="207" width="683" height="486" key="find.popup" timestamp="1582564254151">
<state x="378" y="207" width="683" height="486" key="find.popup" timestamp="1586846937826">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="378" y="207" width="683" height="486" key="find.popup/0.0.1440.900@0.0.1440.900" timestamp="1582564254151" />
<state x="378" y="207" width="683" height="486" key="find.popup/0.0.1440.900@0.0.1440.900" timestamp="1586846937826" />
<state x="398" y="248" key="git4idea.merge.GitPullDialog" timestamp="1582971880352">
<screen x="0" y="0" width="1440" height="900" />
</state>
@ -794,9 +790,9 @@
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="385" y="210" key="run.anything.popup/0.0.1440.900@0.0.1440.900" timestamp="1581652493432" />
<state x="385" y="196" width="670" height="676" key="search.everywhere.popup" timestamp="1582900522166">
<state x="385" y="196" width="670" height="676" key="search.everywhere.popup" timestamp="1587219643331">
<screen x="0" y="0" width="1440" height="900" />
</state>
<state x="385" y="196" width="670" height="676" key="search.everywhere.popup/0.0.1440.900@0.0.1440.900" timestamp="1582900522166" />
<state x="385" y="196" width="670" height="676" key="search.everywhere.popup/0.0.1440.900@0.0.1440.900" timestamp="1587219643331" />
</component>
</project>

@ -212,6 +212,16 @@ HotSpot JVM把年轻代分为了三部分1个Eden区和2个Survivor区
在GC开始的时候对象只会存在于Eden区和名为“From”的Survivor区Survivor区“To”是空的。紧接着进行GCEden区中所有存活的对象都会被复制到“To”而在“From”区中仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中没有达到阈值的对象会被复制到“To”区域。经过这次GC后Eden区和From区已经被清空。这个时候“From”和“To”会交换他们的角色也就是新的“To”就是上次GC前的“From”新的“From”就是上次GC前的“To”。不管怎样都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程直到“To”区被填满“To”区被填满之后会将所有对象移动到年老代中。
### 动态年龄计算
Hotspot在遍历所有对象时按照年龄从小到大对其所占用的大小进行累积当累积的某个年龄大小超过了survivor区的一半时取这个年龄和MaxTenuringThreshold中更小的一个值作为新的晋升年龄阈值。
JVM引入动态年龄计算主要基于如下两点考虑
1. 如果固定按照MaxTenuringThreshold设定的阈值作为晋升条件 aMaxTenuringThreshold设置的过大原本应该晋升的对象一直停留在Survivor区直到Survivor区溢出一旦溢出发生Eden+Svuvivor中对象将不再依据年龄全部提升到老年代这样对象老化的机制就失效了。 bMaxTenuringThreshold设置的过小“过早晋升”即对象不能在新生代充分被回收大量短期对象被晋升到老年代老年代空间迅速增长引起频繁的Major GC。分代回收失去了意义严重影响GC性能。
2. 相同应用在不同时间的表现不同:特殊任务的执行或者流量成分的变化,都会导致对象的生命周期分布发生波动,那么固定的阈值设定,因为无法动态适应变化,会造成和上面相同的问题。
### 常见的垃圾回收机制
1. 引用计数法:引用计数法是一种简单但速度很慢的垃圾回收技术。每个对象都含有一个引用计数器,当有引用连接至对象时,引用计数加1。当引用离开作用域或被置为null时,引用计数减1。虽然管理引用计数的开销不大,但这项开销在整个程序生命周期中将持续发生。垃圾回收器会在含有全部对象的列表上遍历,当发现某个对象引用计数为0时,就释放其占用的空间。
@ -270,7 +280,6 @@ HotSpot JVM把年轻代分为了三部分1个Eden区和2个Survivor区
双亲委派的意思是如果一个类加载器需要加载类,那么首先它会把这个类请求委派给父类加载器去完成,每一层都是如此。一直递归到顶层,当父加载器无法完成这个请求时,子类才会尝试去加载。
### 双亲委派模型的"破坏"
一个典型的例子便是JNDI服务JNDI现在已经是Java的标准服务它的代码由启动类加载器去加载(在JDK 1.3时放进去的rt.jar)但JNDI的目的就是对资源进行集中管理和查找它需要调用由独立厂商实现并部署在应用程序的ClassPath下的JNDI接口提供者(SPI,Service Provider Interface)的代码,但启动类加载器不可能“认识”这些代码那该怎么办?
@ -318,21 +327,78 @@ HotSpot JVM把年轻代分为了三部分1个Eden区和2个Survivor区
* JConsole
* VisualVM
### JVM调优实战
1. 外部命令导致系统缓慢
### JVM常见参数
1. -Xms20M表示设置JVM启动内存的最小值为20M必须以M为单位
2. -Xmx20M表示设置JVM启动内存的最大值为20M必须以M为单位。将-Xmx和-Xms设置为一样可以避免JVM内存自动扩展。大的项目-Xmx和-Xms一般都要设置到10G、20G甚至还要高
3. -verbose:gc表示输出虚拟机中GC的详细情况
4. -Xss128k表示可以设置虚拟机栈的大小为128k
5. -Xoss128k表示设置本地方法栈的大小为128k。不过HotSpot并不区分虚拟机栈和本地方法栈因此对于HotSpot来说这个参数是无效的
6. -XX:PermSize=10M表示JVM初始分配的永久代方法区的容量必须以M为单位
7. -XX:MaxPermSize=10M表示JVM允许分配的永久代方法区的最大容量必须以M为单位大部分情况下这个参数默认为64M
8. -Xnoclassgc表示关闭JVM对类的垃圾回收
9. -XX:+TraceClassLoading表示查看类的加载信息
10. -XX:+TraceClassUnLoading表示查看类的卸载信息
11. -XX:NewRatio=4表示设置年轻代包括Eden和两个Survivor区/老年代 的大小比值为14这意味着年轻代占整个堆的1/5
12. -XX:SurvivorRatio=8表示设置2个Survivor区1个Eden区的大小比值为2:8这意味着Survivor区占整个年轻代的1/5这个参数默认为8
13. -Xmn20M表示设置年轻代的大小为20M
14. -XX:+HeapDumpOnOutOfMemoryError表示可以让虚拟机在出现内存溢出异常时Dump出当前的堆内存转储快照
15. -XX:+UseG1GC表示让JVM使用G1垃圾收集器
16. -XX:+PrintGCDetails表示在控制台上打印出GC具体细节
17. -XX:+PrintGC表示在控制台上打印出GC信息
18. -XX:PretenureSizeThreshold=3145728表示对象大于31457283M时直接进入老年代分配这里只能以字节作为单位
19. -XX:MaxTenuringThreshold=1表示对象年龄大于1自动进入老年代,如果设置为0的话则年轻代对象不经过Survivor区直接进入年老代。对于年老代比较多的应用可以提高效率。如果将此值设置为一个较大值则年轻代对象会在Survivor区进行多次复制这样可以增加对象在年轻代的存活时间增加在年轻代被回收的概率。
20. -XX:CompileThreshold=1000表示一个方法被调用1000次之后会被认为是热点代码并触发即时编译
21. -XX:+PrintHeapAtGC表示可以看到每次GC前后堆内存布局
22. -XX:+PrintTLAB表示可以看到TLAB的使用情况
23. -XX:+UseSpining开启自旋锁
24. -XX:PreBlockSpin更改自旋锁的自旋次数使用这个参数必须先开启自旋锁
25. -XX:+UseSerialGC表示使用jvm的串行垃圾回收机制该机制适用于单核cpu的环境下
26. -XX:+UseParallelGC表示使用jvm的并行垃圾回收机制该机制适合用于多cpu机制同时对响应时间无强硬要求的环境下使用-XX:ParallelGCThreads=<N>设置并行垃圾回收的线程数,此值可以设置与机器处理器数量相等。
27. -XX:+UseParallelOldGC表示年老代使用并行的垃圾回收机制
28. -XX:+UseConcMarkSweepGC表示使用并发模式的垃圾回收机制该模式适用于对响应时间要求高具有多cpu的环境下
29. -XX:MaxGCPauseMillis=100设置每次年轻代垃圾回收的最长时间如果无法满足此时间JVM会自动调整年轻代大小以满足此值。
30. -XX:+UseAdaptiveSizePolicy设置此选项后并行收集器会自动选择年轻代区大小和相应的Survivor区比例以达到目标系统规定的最低响应时间或者收集频率等此值建议使用并行收集器时一直打开
### JVM调优目标-何时需要做jvm调优
1. heap 内存(老年代)持续上涨达到设置的最大内存值;
2. Full GC 次数频繁;
3. GC 停顿时间过长超过1秒
4. 应用出现OutOfMemory 等内存异常;
5. 应用中有使用本地缓存且占用大量内存空间;
6. 系统吞吐量与响应性能不高或下降。
### JVM调优实战
1. Major GC和Minor GC频繁
首先优化Minor GC频繁问题。通常情况下由于新生代空间较小Eden区很快被填满就会导致频繁Minor GC因此可以通过增大新生代空间来降低Minor GC的频率。例如在相同的内存分配率的前提下新生代中的Eden区增加一倍Minor GC的次数就会减少一半。
扩容Eden区虽然可以减少Minor GC的次数但会增加单次Minor GC时间么扩容后Minor GC时增加了T1扫描时间但省去T2复制对象的时间更重要的是对于虚拟机来说复制对象的成本要远高于扫描成本所以单次Minor GC时间更多取决于GC后存活对象的数量而非Eden区的大小。因此如果堆中短期对象很多那么扩容新生代单次Minor GC时间不会显著增加。
2. 请求高峰期发生GC导致服务可用性下降
由于跨代引用的存在CMS在Remark阶段必须扫描整个堆同时为了避免扫描时新生代有很多对象增加了可中断的预清理阶段用来等待Minor GC的发生。只是该阶段有时间限制如果超时等不到Minor GCRemark时新生代仍然有很多对象我们的调优策略是通过参数强制Remark前进行一次Minor GC从而降低Remark阶段的时间。
另外类似的JVM是如何避免Minor GC时扫描全堆的 经过统计信息显示老年代持有新生代对象引用的情况不足1%根据这一特性JVM引入了卡表card table来实现这一目的。卡表的具体策略是将老年代的空间分成大小为512B的若干张卡card。卡表本身是单字节数组数组中的每个元素对应着一张卡当发生老年代引用新生代时虚拟机将该卡对应的卡表元素设置为适当的值。如上图所示卡表3被标记为脏卡表还有另外的作用标识并发标记阶段哪些块被修改过之后Minor GC时通过扫描卡表就可以很快的识别哪些卡中存在老年代指向新生代的引用。这样虚拟机通过空间换时间的方式避免了全堆扫描。
3. 外部命令导致系统缓慢
一个数字校园应用系统发现请求响应时间比较慢通过操作系统的mpstat工具发现CPU使用率很高并且系统占用绝大多数的CPU资 源的程序并不是应用系统本身。每个用户请求的处理都需要执行一个外部shell脚本来获得系统的一些信息执行这个shell脚本是通过Java的 Runtime.getRuntime().exec()方法来调用的。这种调用方式可以达到目的但是它在Java 虚拟机中是非常消耗资源的操作,即使外部命令本身能很快执行完毕,频繁调用时创建进程 的开销也非常可观。Java虚拟机执行这个命令的过程是:首先克隆一个和当前虚拟机拥有一 样环境变量的进程,再用这个新的进程去执行外部命令,最后再退出这个进程。如果频繁执 行这个操作系统的消耗会很大不仅是CPU内存负担也很重。用户根据建议去掉这个Shell脚本执行的语句改为使用Java的API去获取这些信息后 系统很快恢复了正常。
4. STW过长的GC
2. 由Windows虚拟内存导致的长时间停顿
对于性能要求很高的服务建议将MaxPermSize和MinPermSize设置成一致JDK8开始Perm区完全消失转而使用元空间。而元空间是直接存在内存中不在JVM中Xms和Xmx也设置为相同这样可以减少内存自动扩容和收缩带来的性能损失。虚拟机启动的时候就会把参数中所设定的内存全部化为私有即使扩容前有一部分内存不会被用户代码用到这部分内存在虚拟机中被标识为虚拟内存也不会交给其他进程使用。
一个带心跳检测功能的GUI桌面程序每15秒会发送一次心跳检测信号如果 对方30秒以内都没有信号返回那就认为和对方程序的连接已经断开。程序上线后发现心跳 检测有误报的概率,查询日志发现误报的原因是程序会偶尔出现间隔约一分钟左右的时间完 全无日志输出,处于停顿状态。
5. 由Windows虚拟内存导致的长时间停顿
一个带心跳检测功能的GUI桌面程序每15秒会发送一次心跳检测信号如果 对方30秒以内都没有信号返回那就认为和对方程序的连接已经断开。程序上线后发现心跳 检测有误报的概率,查询日志发现误报的原因是程序会偶尔出现间隔约一分钟左右的时间完 全无日志输出,处于停顿状态。
因为是桌面程序,所需的内存并不大(-Xmx256m)所以开始并没有想到是GC导致的 程序停顿,但是加入参数-XX:+PrintGCApplicationStoppedTime-XX:+PrintGCDateStamps- Xloggc:gclog.log后从GC日志文件中确认了停顿确实是由GC导致的大部分GC时间都控 制在100毫秒以内但偶尔就会出现一次接近1分钟的GC。
从GC日志中找到长时间停顿的具体日志信息(添加了-XX:+PrintReferenceGC参数) 找到的日志片段如下所示。从日志中可以看出真正执行GC动作的时间不是很长但从准 备开始GC到真正开始GC之间所消耗的时间却占了绝大部分。
除GC日志之外还观察到这个GUI程序内存变化的一个特点当它最小化的时候资源 管理中显示的占用内存大幅度减小,但是虚拟内存则没有变化,因此怀疑程序在最小化时它 的工作内存被自动交换到磁盘的页面文件之中了这样发生GC时就有可能因为恢复页面文 件的操作而导致不正常的GC停顿。在Java的GUI程序中要避免这种现象可以 加入参数“-Dsun.awt.keepWorkingSetOnMinimize=true”来解决。
## Java基础
@ -377,6 +443,10 @@ CAS是英文单词CompareAndSwap的缩写中文意思是比较并替换。
AQS内部有3个对象一个是state用于计数器类似gc的回收计数器一个是线程标记当前线程是谁加锁的一个是阻塞队列。
AQS是自旋锁在等待唤醒的时候经常会使用自旋的方式不停地尝试获取锁直到被其他线程获取成功。
AQS有两个队列同步对列和条件队列。同步队列依赖一个双向链表来完成同步状态的管理当前线程获取同步状态失败后同步器会将线程构建成一个节点并将其加入同步队列中。通过signal或signalAll将条件队列中的节点转移到同步队列。
### 如何指定多个线程的执行顺序
1. 设定一个 orderNum每个线程执行结束之后更新 orderNum指明下一个要执行的线程。并且唤醒所有的等待线程。

Loading…
Cancel
Save